这个主要讲的InputStream去保存。
如果需要BItmap与InputStream相互转换可以参考
Android Bitmap、InputStream、Drawable、byte[]、Base64之间的转换关系
Android 手机下载图片保存本地后,系统相册无法查看
保存图片我们需要考虑系统版本,Q前后还是不一样的。
/**
* 保存图片
* @param context 上下文
* @param inputStream 流
* @param suffixName 后缀名(.png .jpg)
* @return
* @throws IOException
*/
public static String saveImageFromInput(Context context, InputStream inputStream, String suffixName) throws IOException {
if (androidQ()) {
Uri uri = saveImageFromInputByAndroidQMedia(context, inputStream, suffixName);
String imagePathByUri = getImagePathByUri(context, uri);
return imagePathByUri;
} else {
String imagePtah = createFilePath(context, suffixName,randomName() + suffixName).getAbsolutePath();
saveImageFromInputByAndroid(context, inputStream, imagePtah);
return imagePtah;
}
}
/**
* 保存媒体库(AndroidQ)
* @param context
* @param inputStream
* @param suffixName
* @return
*/
private static Uri saveImageFromInputByAndroidQMedia(Context context, InputStream inputStream, String suffixName) {
BufferedInputStream bis = null;
OutputStream outputStream = null;
BufferedOutputStream bos = null;
Uri uri = null;
try {
bis = new BufferedInputStream(inputStream);
uri = getImageUriByMediaStore(context, suffixName);
if (uri != null) {
outputStream = context.getContentResolver().openOutputStream(uri);
if (outputStream != null) {
bos = new BufferedOutputStream(outputStream);
byte[] buf = new byte[102400];
int bytes = bis.read(buf);
while (bytes >= 0) {
bos.write(buf, 0, bytes);
bos.flush();
bytes = bis.read(buf);
}
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
closeSilently(bis);
closeSilently(bos);
closeSilently(outputStream);
return uri;
}
}
/**
* 保存本地
* @param context
* @param inputStream
* @param imagePath
*/
private static void saveImageFromInputByAndroid(Context context, InputStream inputStream, String imagePath) {
BufferedInputStream bis = null;
OutputStream outputStream = null;
BufferedOutputStream bos = null;
try {
bis = new BufferedInputStream(inputStream);
outputStream = new FileOutputStream(imagePath);
if (outputStream != null) {
bos = new BufferedOutputStream(outputStream);
byte[] buf = new byte[102400];
int bytes = bis.read(buf);
while (bytes >= 0) {
bos.write(buf, 0, bytes);
bos.flush();
bytes = bis.read(buf);
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
closeSilently(bis);
closeSilently(bos);
closeSilently(outputStream);
}
}
public static Uri getImageUriByMediaStore(Context context, String suffixName) throws IOException {
Uri uri;
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
// 7.0之前获取uri方式
uri = Uri.fromFile(createFilePath(context, "image", randomName() + suffixName));
} else if (androidQ()) {
ContentValues contentValues = new ContentValues();
contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, randomName() + suffixName);
contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/*");
contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DCIM);
uri = context.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);
} else {
//7.0之后获取uri方式
uri = FileProvider.getUriForFile(context, FileAppProvider.getProviderName(context), createFilePath(context, "image", randomName() + suffixName));
}
return uri;
}
/**
* 创建文件路径
* @param context
* @param folderName
* @param fileName
* @return
* @throws IOException
*/
private static File createFilePath(Context context, String folderName, String fileName) throws IOException {
String path;
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/app/" + folderName + "/" + fileName;
} else {
path = context.getCacheDir().getAbsolutePath() + "/app/" + folderName + "/" + fileName;
}
return createFile(new File(path));
}
/**
* 创建文件
* @param imageFile
* @return
* @throws IOException
*/
private static File createFile(File imageFile) throws IOException {
if (!imageFile.getParentFile().exists()) {
imageFile.getParentFile().mkdirs();
}
if (imageFile.exists()) {
imageFile.delete();
}
if (!imageFile.exists()) {
imageFile.createNewFile();
}
return imageFile;
}
/**
* 获取uri 对应 path
* @param context
* @param uri
* @return
*/
public static String getImagePathByUri(Context context, Uri uri) {
String imagePath = null;
if (context != null && uri != null) {
String[] proj = {MediaStore.Images.Media.DATA};
Cursor cursor = context.getContentResolver().query(uri, proj, null, null, null);
if (cursor.moveToFirst()) {
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
imagePath = cursor.getString(column_index);
}
cursor.close();
}
return imagePath;
}
public static void closeSilently(Closeable c) {
if (c == null) return;
try {
c.close();
} catch (Throwable t) {
// Do nothing
}
}
public static boolean androidQ() {
return Build.VERSION.SDK_INT > Build.VERSION_CODES.Q;
}
/**
* 生成随机名称
*
* @return
*/
public static String randomName() {
return System.currentTimeMillis() + "_" + new Random().nextInt();
}
FileAppProvider
public class FileAppProvider extends FileProvider {
public static String getProviderName(Context context) {
return context.getPackageName() + ".app.file.app.provider";
}
}
file_app_provider.xml
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2017 Yan Zhenjie.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<paths>
<external-path
name="external_path"
path="."/>
<external-files-path
name="external_files_path"
path="."/>
<external-cache-path
name="external_cache_path"
path="."/>
<files-path
name="file_path"
path="."/>
<cache-path
name="cache_path"
path="."/>
</paths>
清单文件添加:
<provider
android:name="com.app.file.provider.FileZqcfProvider"
android:authorities="${applicationId}.app.file.app.provider"
android:exported="false"
android:grantUriPermissions="true"
android:multiprocess="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_app_provider" />
</provider>