生活随笔
收集整理的這篇文章主要介紹了
Android WebView 调用相机、相册,压缩图片后上传
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
Android WebView 調用相機、相冊,壓縮圖片后上傳
聲明:文中代碼根據多篇博客進行修改,由本人縫合而成,對應地方會放出原文鏈接。
重寫webChromeClient的onShowFileChooser方法
@Overridepublic boolean onShowFileChooser(WebView webView
, ValueCallback<Uri[]> filePathCallback
, FileChooserParams fileChooserParams
) {mUploadCallbackAboveL
= filePathCallback
;openAlbum();return true;}
fileChooserParams可以接收h5中input標簽的一些參數,選擇好文件后,將文件uri傳遞給filePathCallback。
原文鏈接:調用原生相機、相冊
選擇調用相機或相冊
private void openAlbum() {String filePath
= Environment.getExternalStorageDirectory() + File.separator
+ Environment.DIRECTORY_PICTURES
+ File.separator
;String fileName
= "IMG_" + DateFormat.format("yyyyMMdd_hhmmss", Calendar.getInstance(Locale.CHINA
)) + ".jpg";image
= new File(filePath
+ fileName
);imageUri
= Uri.fromFile(image
);Intent captureIntent
= new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE
);captureIntent
.putExtra(MediaStore.EXTRA_OUTPUT
, imageUri
);Intent Photo = new Intent(Intent.ACTION_PICK
, MediaStore.Images.Media.EXTERNAL_CONTENT_URI
);Intent chooserIntent
= Intent.createChooser(Photo, "選擇照片");chooserIntent
.putExtra(Intent.EXTRA_INITIAL_INTENTS
, new Parcelable[]{captureIntent
});startActivityForResult(chooserIntent
, REQUEST_CODE
);}
通過imageUri保存調用相機拍照的照片的存儲位置。用Intent打開選擇相機、相冊或文件夾的activity。
接收選擇照片,或者拍照返回的uri
@Overrideprotected void onActivityResult(int requestCode
, int resultCode
, Intent data
) {super.onActivityResult(requestCode
, resultCode
, data
);if (requestCode
== REQUEST_CODE
) {if (mUploadCallbackAboveL
!= null) {chooseAbove(resultCode
, data
);} else {Toast.makeText(this, "發生錯誤", Toast.LENGTH_SHORT
).show();}}}
choosAbove方法來處理獲取后的uri,并回傳給filePathCallback。
處理uri
具體的處理步驟,通過uri獲取到圖片的path,讀取圖片,壓縮圖片后重新存儲,將壓縮后的圖片uri進行回傳
(1). chooseAbove方法
private void chooseAbove(int resultCode
, Intent data
) {if (RESULT_OK
== resultCode
) {updatePhotos();if (data
!= null) {
Uri[] results
;Uri uriData
= data
.getData();if (uriData
!= null) {results
= new Uri[]{uriData
};try {Uri compressImageUri
= ImageCompressUtils.compressBmpFromBmp(uriToString(uriData
));mUploadCallbackAboveL
.onReceiveValue(new Uri[]{compressImageUri
});} catch (Exception e
) {e
.printStackTrace();requestWritePermission();}} else {mUploadCallbackAboveL
.onReceiveValue(null);}} else {
try {Uri compressImageUri
= ImageCompressUtils.compressBmpFromBmp(imageUri
.getPath());mUploadCallbackAboveL
.onReceiveValue(new Uri[]{compressImageUri
});} catch (Exception e
) {e
.printStackTrace();requestWritePermission();}}} else {mUploadCallbackAboveL
.onReceiveValue(null);}mUploadCallbackAboveL
= null;}
由于拍照的照片存儲在imageUri,這里將拍照和相冊選擇分開處理,注意,如果沒有選擇照片,給filePathCallback傳一個空值,防止上傳只能點擊一次后失效。
(2). 壓縮圖片的工具類ImageCompressUtils
原文鏈接圖片壓縮工具類(解決了壓縮后圖片被旋轉的問題)
public class ImageCompressUtils {public static Uri compressBmpFromBmp(String srcPath
) {
BitmapFactory.Options newOptions
= new BitmapFactory.Options();newOptions
.inJustDecodeBounds
= true;Bitmap bitmap
= BitmapFactory.decodeFile(srcPath
, newOptions
);newOptions
.inJustDecodeBounds
= false;int w
= newOptions
.outWidth
;int h
= newOptions
.outHeight
;float hh
= 800f;float ww
= 480f;int be
= 1;if (w
> h
&& w
> ww
) {be
= (int) (newOptions
.outWidth
/ ww
);} else if (w
< h && h > hh
) {be
= (int) (newOptions
.outHeight
/ hh
);}if (be
<= 0)be
= 1;newOptions
.inSampleSize
= be
;newOptions
.inPreferredConfig
= Bitmap.Config.ARGB_8888
;newOptions
.inPurgeable
= true;newOptions
.inInputShareable
= true;bitmap
= BitmapFactory.decodeFile(srcPath
, newOptions
);int degree
= readPictureDegree(srcPath
);bitmap
= rotateBitmap(bitmap
, degree
);return compressBmpToFile(bitmap
);}public static Uri compressBmpToFile(Bitmap bmp
) {String path
= Environment.getExternalStorageDirectory().getAbsolutePath() + "/shoppingMall/compressImgs/";File file
= new File(path
+ System.currentTimeMillis() + ".jpg");if (!file
.getParentFile().exists()) {file
.getParentFile().mkdirs();}ByteArrayOutputStream baos
= new ByteArrayOutputStream();int options
= 80;bmp
.compress(Bitmap.CompressFormat.JPEG
, options
, baos
);while (baos
.toByteArray().length
/ 1024 > 100) {baos
.reset();options
-= 10;bmp
.compress(Bitmap.CompressFormat.JPEG
, options
, baos
);}try {FileOutputStream fos
= new FileOutputStream(file
);fos
.write(baos
.toByteArray());fos
.flush();fos
.close();
return Uri.fromFile(file
);} catch (FileNotFoundException e
) {
e
.printStackTrace();} catch (IOException e
) {
e
.printStackTrace();}return null;}private static int readPictureDegree(String srcPath
) {int degree
= 0;try {ExifInterface exifInterface
= new ExifInterface(srcPath
);int orientation
= exifInterface
.getAttributeInt(ExifInterface.TAG_ORIENTATION
, ExifInterface.ORIENTATION_NORMAL
);switch (orientation
) {case ExifInterface.ORIENTATION_ROTATE_90
:degree
= 90;break;case ExifInterface.ORIENTATION_ROTATE_180
:degree
= 180;break;case ExifInterface.ORIENTATION_ROTATE_270
:degree
= 270;break;}} catch (IOException e
) {e
.printStackTrace();}return degree
;}private static Bitmap rotateBitmap(Bitmap bitmap
, int rotate
) {if (bitmap
== null)return null;int w
= bitmap
.getWidth();int h
= bitmap
.getHeight();Matrix mtx
= new Matrix();mtx
.postRotate(rotate
);return Bitmap.createBitmap(bitmap
, 0, 0, w
, h
, mtx
, true);}}
調用壓縮方法,將壓縮后的圖片的uri傳遞給filePathCallback,上傳結束。
5.需要注意的地方
如果應用沒有文件存儲的權限,要動態請求權限。一下是請求權限及其回調方法。
原文鏈接:動態獲取文件存儲權限
private void requestWritePermission() {if (checkSelfPermission(Manifest.permission
.WRITE_EXTERNAL_STORAGE
) != PackageManager.PERMISSION_GRANTED
) {ActivityCompat.requestPermissions(this, new String[]{Manifest.permission
.WRITE_EXTERNAL_STORAGE
}, WRITE_PERMISSION
);}}@Overridepublic void onRequestPermissionsResult(int requestCode
, String permissions
[], int[] grantResults
) {if (requestCode
== WRITE_PERMISSION
) {if (grantResults
[0] != PackageManager.PERMISSION_GRANTED
) {String message
= "必須提供文件存儲權限,否則無法正常使用.";AlertDialog.Builder localBuilder
= new AlertDialog.Builder(webView
.getContext());localBuilder
.setMessage(message
).setPositiveButton(getResources().getString(R.string
.sure
), new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog
, int which
) {requestWritePermission();}});localBuilder
.setCancelable(false);localBuilder
.create().show();}}}
通過uri獲取path的問題
imageUri保存的圖片,通過getPath可以直接獲取。但是相冊和文件夾選擇的uri,getPath獲取到的路徑在讀取照片時卻找不到。因此,使用如下方法,通過uri獲取path。
原文地址:uri獲取path
private String uriToString(Uri uri
) {String path
= null;if (ContentResolver.SCHEME_CONTENT
.equals(uri
.getScheme())) {if (DocumentsContract.isDocumentUri(this, uri
)) {if ("com.android.externalstorage.documents".equals(uri
.getAuthority())) {String docId
= DocumentsContract.getDocumentId(uri
);String[] split
= docId
.split(":");String type
= split
[0];if ("primary".equalsIgnoreCase(type
)) {path
= Environment.getExternalStorageDirectory() + "/" + split
[1];}} else if ("com.android.providers.downloads.documents".equals(uri
.getAuthority())) {String id
= DocumentsContract.getDocumentId(uri
);Uri contentUri
= ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(id
));path
= getDataColumn(this, contentUri
, null, null);} else if ("com.android.providers.media.documents".equals(uri
.getAuthority())) {String docId
= DocumentsContract.getDocumentId(uri
);String[] split
= docId
.split(":");String type
= split
[0];Uri contentUri
= null;if ("image".equals(type
)) {contentUri
= MediaStore.Images.Media.EXTERNAL_CONTENT_URI
;} else if ("video".equals(type
)) {contentUri
= MediaStore.Video.Media.EXTERNAL_CONTENT_URI
;} else if ("audio".equals(type
)) {contentUri
= MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
;}String selection
= "_id=?";String[] selectionArgs
= new String[]{split
[1]};path
= getDataColumn(this, contentUri
, selection
, selectionArgs
);}} else {path
= getRealPathFromUri(this, uri
);}}return path
;}private String getRealPathFromUri(Context context
, Uri contentUri
) {Cursor cursor
= null;try {String[] proj
= {MediaStore.Files.FileColumns.DATA
};cursor
= context
.getContentResolver().query(contentUri
, proj
, null, null, null);int column_index
= cursor
.getColumnIndexOrThrow(MediaStore.Files.FileColumns.DATA
);cursor
.moveToFirst();return cursor
.getString(column_index
);} finally {if (cursor
!= null) {cursor
.close();}}}private String getDataColumn(Context context
, Uri uri
, String selection
, String[] selectionArgs
) {Cursor cursor
= null;final String column
= "_data";final String[] projection
= {column
};try {cursor
= context
.getContentResolver().query(uri
, projection
, selection
, selectionArgs
, null);if (cursor
!= null && cursor
.moveToFirst()) {final int column_index
= cursor
.getColumnIndexOrThrow(column
);return cursor
.getString(column_index
);}} finally {if (cursor
!= null)cursor
.close();}return null;}
拍照后,廣播通知系統刷新文件
private void updatePhotos() {Intent intent
= new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE
);intent
.setData(imageUri
);sendBroadcast(intent
);}
總結
以上是生活随笔為你收集整理的Android WebView 调用相机、相册,压缩图片后上传的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。