前言:
这个纯属笔记 如果你是做APP 可以用方便三方库来实现更好,废话不多说我们正式开始
效果图:
image.png布局代码:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".TestActivity">
<Button
android:id="@+id/getimg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="上传图片"
android:layout_marginTop="10dp"
>
</Button>
<Button
android:id="@+id/getvideo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="上传视频"
android:layout_marginTop="10dp"
>
</Button>
<ImageView
android:id="@+id/test_img"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</ImageView>
</LinearLayout>
布局预览
image.png我们就写了2个button 分别来触发这个上传图片和上传视频的事件
从相册中选择图片
/**
* 从相册中选择图片
*/
private void openPhoto(int openPhotoCode){
Intent intent = new Intent(Intent.ACTION_PICK, null);
intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
startActivityForResult(intent, openPhotoCode);
}
从相册中选择视频
/**
* 从相册中选择视频
*/
private void choiceVideo(int openVideoCode) {
Intent i = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Video.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(i, openVideoCode);
}
我们封装2个方法分别打开相册获取视频和图片的
//获取图片
findViewById(R.id.getimg).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
int hasWritePermission = checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE);
List<String> permissions = new ArrayList<String>();
if (hasWritePermission != PackageManager.PERMISSION_GRANTED) {
permissions.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
} else {
openPhoto(1);
}
if (!permissions.isEmpty()) {
ActivityCompat.requestPermissions((Activity) mContext, new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE},
REQUEST_PERMISSION);
}
}else {
openPhoto(1);
}
}
});
// 获取视频
findViewById(R.id.getvideo).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
int hasWritePermission = checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE);
List<String> permissions = new ArrayList<String>();
if (hasWritePermission != PackageManager.PERMISSION_GRANTED) {
permissions.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
} else {
choiceVideo(6);
}
if (!permissions.isEmpty()) {
ActivityCompat.requestPermissions((Activity) mContext, new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE},
REQUEST_PERMISSION);
}
}else {
choiceVideo(6);
}
}
});
获取图片和视频结果处理
我们在 onActivityResult 方法里面来处理 我们分别写了 getphotoResult方法和getVideoFileResult 方法来处理视频结果图片结果
protected void onActivityResult(int requestCode, int resultCode, Intent data){
super.onActivityResult(requestCode, resultCode, data);
if (requestCode >=1&&requestCode<=5) {
// 从相册返回的数据
if (data != null) {
getphotoResult(requestCode,resultCode,data);
}
}else if (requestCode>=6&&requestCode<=10 && resultCode == RESULT_OK && null != data) {
getVideoFileResult(requestCode,resultCode,data);
}
if (resultCode != Activity.RESULT_OK) {
return;
}
}
图片结果处理
//处理获取到的图片文件
private void getphotoResult(int requestCode, int resultCode, Intent data){
// 得到图片的全路径
if(requestCode==1){
Uri uri = data.getData();
Log.e(TAG, "onActivityResult:uri "+uri );
testimage.setImageURI(uri);
String imagePath = ImageUtils.getImagePath(uri, null, (Activity) mContext);
Log.e(TAG, "onActivityResult:imagePath "+imagePath);
if(!TextUtils.isEmpty(imagePath)){
File file=new File(imagePath);
}
}
}
视频结果处理
//处理获取到视频文件
private void getVideoFileResult(int requestCode, int resultCode, Intent data){
Uri selectedVideo = data.getData();
String[] filePathColumn = {MediaStore.Video.Media.DATA};
Cursor cursor = getContentResolver().query(selectedVideo,
filePathColumn, null, null, null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
String videopath = cursor.getString(columnIndex);
Log.e(TAG, "onActivityResult:VIDEOPATH --- > "+ videopath);
Double size= FileSizeUtil.getFileOrFilesSize(videopath,3);
Log.e(TAG, "onActivityResult:size --- > "+size);
if(size<30.0){
File viodefile=new File(videopath);
}else{
Toast.makeText(mContext,"视频大小不能超过30MB请调整大小",Toast.LENGTH_SHORT).show();
}
cursor.close();
}
图片 视频 URI 转换工具类
package com.example.camerademo;
import android.app.Activity;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.provider.MediaStore;
import android.widget.ImageView;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
/**
*
* 创建人:xuqing
* 创建时间:2020年8月25日16:42:38
* 类说明:图片加载类
*
*/
public class ImageUtils {
//加载网络图片
public static void showImage(final Activity context, final String url, final ImageView
imageView){
new Thread(new Runnable() {
@Override
public void run() {
final Bitmap bitmap=getImageBitmap(url);
context.runOnUiThread(new Runnable() {
@Override
public void run() {
imageView.setImageBitmap(bitmap);
}
});
}
}).start();
}
//将图片URL地址转换成Bitmap
public static Bitmap getImageBitmap(String url) {
URL imgUrl = null;
Bitmap bitmap = null;
try {
imgUrl = new URL(url);
HttpURLConnection conn = (HttpURLConnection) imgUrl
.openConnection();
conn.setDoInput(true);
conn.connect();
InputStream is = conn.getInputStream();
bitmap = BitmapFactory.decodeStream(is);
is.close();
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return bitmap;
}
// 将uri 转换成path路径
public static String getImagePath(Uri uri, String selection, Activity activity) {
String path = null;
Cursor cursor = activity.getContentResolver().query(uri,
null, selection, null, null);
if (cursor != null) {
if (cursor.moveToFirst()) {
path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
}
cursor.close();
}
return path;
}
}
文件大小工具检查工具类
package com.example.camerademo;
import android.util.Log;
import java.io.File;
import java.io.FileInputStream;
import java.text.DecimalFormat;
/**
*
* 创建人:xuqing
* 创建时间:2021年8月27日15:30:02
* 类说明:文件大小工具类
*
*
*/
public class FileSizeUtil {
private static final String TAG=FileSizeUtil.class.getSimpleName();
public static final int SIZETYPE_B = 1;//获取文件大小单位为B的double值
public static final int SIZETYPE_KB = 2;//获取文件大小单位为KB的double值
public static final int SIZETYPE_MB = 3;//获取文件大小单位为MB的double值
public static final int SIZETYPE_GB = 4;//获取文件大小单位为GB的double值
/**
* 获取文件指定文件的指定单位的大小
*
* @param filePath 文件路径
* @param sizeType 获取大小的类型1为B、2为KB、3为MB、4为GB
* @return double值的大小
*/
public static double getFileOrFilesSize(String filePath, int sizeType) {
File file = new File(filePath);
long blockSize = 0;
try {
if (file.isDirectory()) {
blockSize = getFileSizes(file);
} else {
blockSize = getFileSize(file);
}
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG,"获取文件大小失败!");
}
return FormetFileSize(blockSize, sizeType);
}
/**
* 调用此方法自动计算指定文件或指定文件夹的大小
*
* @param filePath 文件路径
* @return 计算好的带B、KB、MB、GB的字符串
*/
public static String getAutoFileOrFilesSize(String filePath) {
File file = new File(filePath);
long blockSize = 0;
try {
if (file.isDirectory()) {
blockSize = getFileSizes(file);
} else {
blockSize = getFileSize(file);
}
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG,"获取文件大小失败!");
}
return FormetFileSize(blockSize);
}
/**
* 获取指定文件大小
*
* @param file
* @return
* @throws Exception
*/
private static long getFileSize(File file) throws Exception {
long size = 0;
if (file.exists()) {
FileInputStream fis = null;
fis = new FileInputStream(file);
size = fis.available();
} else {
file.createNewFile();
Log.e(TAG,"获取文件大小不存在!");
}
return size;
}
/**
* 获取指定文件夹
*
* @param f
* @return
* @throws Exception
*/
private static long getFileSizes(File f) throws Exception {
long size = 0;
File flist[] = f.listFiles();
for (int i = 0; i < flist.length; i++) {
if (flist[i].isDirectory()) {
size = size + getFileSizes(flist[i]);
} else {
size = size + getFileSize(flist[i]);
}
}
return size;
}
/**
* 转换文件大小
*
* @param fileS
* @return
*/
private static String FormetFileSize(long fileS) {
DecimalFormat df = new DecimalFormat("#.00");
String fileSizeString = "";
String wrongSize = "0B";
if (fileS == 0) {
return wrongSize;
}
if (fileS < 1024) {
fileSizeString = df.format((double) fileS) + "B";
} else if (fileS < 1048576) {
fileSizeString = df.format((double) fileS / 1024) + "KB";
} else if (fileS < 1073741824) {
fileSizeString = df.format((double) fileS / 1048576) + "MB";
} else {
fileSizeString = df.format((double) fileS / 1073741824) + "GB";
}
return fileSizeString;
}
/**
* 转换文件大小,指定转换的类型
*
* @param fileS
* @param sizeType
* @return
*/
private static double FormetFileSize(long fileS, int sizeType) {
DecimalFormat df = new DecimalFormat("#.00");
double fileSizeLong = 0;
switch (sizeType) {
case SIZETYPE_B:
fileSizeLong = Double.valueOf(df.format((double) fileS));
break;
case SIZETYPE_KB:
fileSizeLong = Double.valueOf(df.format((double) fileS / 1024));
break;
case SIZETYPE_MB:
fileSizeLong = Double.valueOf(df.format((double) fileS / 1048576));
break;
case SIZETYPE_GB:
fileSizeLong = Double.valueOf(df.format((double) fileS / 1073741824));
break;
default:
break;
}
return fileSizeLong;
}
}
其他说明 :
Android在4.4之后的版本(包括4.4)中,从相册中选取图片返回Uri进行了改动。所以我们无法通过该Uri来取得文件路径,从而解码图片,将其显示出来。
在4.3或以下可以直接用Intent.ACTION_GET_CONTENT打开相册;在4.4或以上,官方建议用ACTION_OPEN_DOCUMENT打开相册
-
4.4之前的版本
在4.4之前的版本,返回的Uri如下:content://media/external/images/media/8302
我们可以通过ContentResolver的查询方法来获取路径:
Uri uri = "content://media/external/images/media/8302";
String imagePath = getImagePath(uri, null);
private String getImagePath(Uri uri, String selection) {
String path = null;
Cursor cursor = getContentResolver().query(uri, null, selection, null, null);
if (cursor != null) {
if (cursor.moveToFirst()) {
path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
}
cursor.close();
}
return path;
}
代码分析,当我们通过uri得到了相册数据库图片的表,然后通过索引MediaStore.Images.Media.DATA获取所得行的"_data"列的值。这样我们就得到了具体的文件路径,可以通过创建输入流来获取相应的Bitmap,并进行显示。
-
4.4之后的版本,包括4.4
在4.4之后的,包括4.4的版本,返回的Uri有可能是以下的一种:
- content://com.android.providers.media.documents/document/image%3A8302
- content://com.android.providers.downloads.documents/document/5
-
content://media/external/images/media/8302
我们不能直接通过前两种Uri直接获取到对应的表,所以需要"翻译一下":
private void handleImageOnKitKat(Intent data) {
String imagePath = null;
Uri uri = data.getData();
if (DocumentsContract.isDocumentUri(this, uri)) {
String docId = DocumentsContract.getDocumentId(uri);
if ("com.android.providers.media.documents".equals(uri.getAuthority())) {
//Log.d(TAG, uri.toString());
String id = docId.split(":")[1];
String selection = MediaStore.Images.Media._ID + "=" + id;
imagePath = getImagePath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, selection);
} else if ("com.android.providers.downloads.documents".equals(uri.getAuthority())) {
//Log.d(TAG, uri.toString());
Uri contentUri = ContentUris.withAppendedId(
Uri.parse("content://downloads/public_downloads"),
Long.valueOf(docId));
imagePath = getImagePath(contentUri, null);
}
} else if ("content".equalsIgnoreCase(uri.getScheme())) {
//Log.d(TAG, "content: " + uri.toString());
imagePath = getImagePath(uri, null);
}
}
代码分析:
判断步骤:
1首先对Uri的authority进行判断。是document类型的Uri还是普通的media类型的Uri。
由于document类型有两种:media和download类型,所以需要进一步判断。因为这里涉及Uri的id部分不同。
2 如果是普通类型,那么和4.4之前的处理完全一样。可以直接通过Uri获取文件路径。
3 如果是media类型的document Uri,我们首先通过DocumentsContract.getDocumentId(uri);获取到"image%3A8302"。然后通过String.split方法来获取真正的id。
参考
Android 4.4从图库选择图片,获取图片路径并裁剪
Android-Uri To Path
最后总结
调用相册或者相机 获取手机内存里面视频或者图片文件 是比较常见的需求 ,因为是做手游SDK开发所以基本很少去看这些原生写法 所以就做个笔记记录下
网友评论