fix MediaSelector

androidx
Ztiany 5 years ago
parent d6b0514f4c
commit aea71da6c6
  1. 10
      lib_base/src/main/java/com/android/base/data/State.kt
  2. 28
      lib_media_selector/src/main/java/com/android/sdk/mediaselector/StyleUtils.java
  3. 154
      lib_media_selector/src/main/java/com/android/sdk/mediaselector/SystemMediaSelector.java
  4. 188
      lib_media_selector/src/main/java/com/android/sdk/mediaselector/Utils.java

@ -1,5 +1,7 @@
package com.android.base.data package com.android.base.data
import androidx.lifecycle.MutableLiveData
/** /**
* @author Ztiany * @author Ztiany
@ -200,4 +202,12 @@ inline fun <T> State<T>.onSuccessWithData(onSuccess: (data: T) -> Unit): State<T
onSuccess(t) onSuccess(t)
} }
return this return this
}
fun <T : Any?> MutableLiveData<State<T>>.postLoading() {
postValue(State.loading())
}
fun <T : Any?> MutableLiveData<State<T>>.postError(error: Throwable) {
postValue(State.error(error))
} }

@ -0,0 +1,28 @@
package com.android.sdk.mediaselector;
import android.content.Context;
import android.os.Build;
import android.util.TypedValue;
/**
* @author Ztiany
* Email: ztiany3@gmail.com
* Date : 2019-11-22 11:36
*/
class StyleUtils {
//https://stackoverflow.com/questions/27611173/how-to-get-accent-color-programmatically
static int fetchPrimaryColor(Context context) {
int colorAttr;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
colorAttr = android.R.attr.colorPrimary;
} else {
//Get colorAccent defined for AppCompat
colorAttr = context.getResources().getIdentifier("colorPrimary", "attr", context.getPackageName());
}
TypedValue outValue = new TypedValue();
context.getTheme().resolveAttribute(colorAttr, outValue, true);
return outValue.data;
}
}

@ -9,6 +9,7 @@ import android.util.Log;
import java.io.File; import java.io.File;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
/** /**
@ -29,6 +30,7 @@ public class SystemMediaSelector {
private static final int REQUEST_CROP = 197; private static final int REQUEST_CROP = 197;
private static final int REQUEST_ALBUM = 198; private static final int REQUEST_ALBUM = 198;
private static final int REQUEST_FILE = 199; private static final int REQUEST_FILE = 199;
private static final int REQUEST_LINRARY_CROP = 200;
private static final String POSTFIX = ".file.provider"; private static final String POSTFIX = ".file.provider";
private String mAuthority; private String mAuthority;
@ -37,11 +39,18 @@ public class SystemMediaSelector {
private Activity mActivity; private Activity mActivity;
private Fragment mFragment; private Fragment mFragment;
private String mSavePhotoPath;
private CropOptions mCropOptions;
private final CropOptions mDefaultOptions = new CropOptions(); private final CropOptions mDefaultOptions = new CropOptions();
private String mCropTitle; private String mCropTitle;
private boolean mNeedCrop; private boolean mNeedCrop;
private CropOptions mCropOptions;
/*使用内部的裁剪库(推荐,系统裁剪兼容性差)*/
private boolean mUseInnerCrop = true;
/*用于保存图片*/
private String mSavePhotoPath;
/*某些手机,拍照和裁剪不能是同一个路径*/
private String mSavePhotoPathForCropCamera;
public SystemMediaSelector(Activity activity, MediaSelectorCallback systemMediaSelectorCallback) { public SystemMediaSelector(Activity activity, MediaSelectorCallback systemMediaSelectorCallback) {
mActivity = activity; mActivity = activity;
@ -57,10 +66,10 @@ public class SystemMediaSelector {
private void init() { private void init() {
mAuthority = getContext().getPackageName().concat(POSTFIX); mAuthority = getContext().getPackageName().concat(POSTFIX);
mDefaultOptions.setAspectX(1); mDefaultOptions.setAspectX(0);
mDefaultOptions.setAspectY(1); mDefaultOptions.setAspectY(0);
mDefaultOptions.setOutputX(1000); mDefaultOptions.setOutputX(0);
mDefaultOptions.setOutputY(1000); mDefaultOptions.setOutputY(0);
} }
private Context getContext() { private Context getContext() {
@ -95,55 +104,50 @@ public class SystemMediaSelector {
return mCropOptions == null ? mDefaultOptions : mCropOptions; return mCropOptions == null ? mDefaultOptions : mCropOptions;
} }
public void setUseInnerCrop(boolean useInnerCrop) {
mUseInnerCrop = useInnerCrop;
}
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// Take method // take photo from camera
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
public boolean takePhotoFromCamera(String savePath) { public boolean takePhotoFromCamera(String savePath) {
mSavePhotoPath = savePath; mSavePhotoPath = savePath;
mNeedCrop = false; mNeedCrop = false;
return toCamera(); return toCamera(mSavePhotoPath);
} }
/** /**
* 为了保证裁裁剪图片不出问题务必指定CropOptions中的各个参数(不要为0比如魅族手机如果指定OutputX和OutputY为0则只会裁减出一个像素)否则可能出现问题 * 为了保证裁裁剪图片不出问题务必指定CropOptions中的各个参数(不要为0比如魅族手机如果指定OutputX和OutputY为0则只会裁减出一个像素)否则可能出现问题
*/ */
public boolean takePhotoFromCameraAndCrop(String savePath, CropOptions cropOptions, String cropTitle) { public boolean takePhotoFromCameraAndCrop(String savePath, @Nullable CropOptions cropOptions, String cropTitle) {
mSavePhotoPath = savePath; mSavePhotoPath = savePath;
mSavePhotoPathForCropCamera = Utils.addFilePostfix(mSavePhotoPath, "camera");
mNeedCrop = true; mNeedCrop = true;
mCropOptions = cropOptions; mCropOptions = cropOptions;
mCropTitle = cropTitle; mCropTitle = cropTitle;
return toCamera(); return toCamera(mSavePhotoPathForCropCamera);
}
public boolean takePhotoFormAlbum() {
mNeedCrop = false;
try {
startActivityForResult(Utils.makeAlbumIntent(), REQUEST_ALBUM);
return true;
} catch (Exception e) {
return false;
}
} }
public boolean takePhotoFormAlbumAndCrop(String savePhotoPath, CropOptions cropOptions, String cropTitle) { private boolean toCropPhotoFromCamera() {
mNeedCrop = true; File targetFile = new File(mSavePhotoPath);
mSavePhotoPath = savePhotoPath; File srcFile = new File(mSavePhotoPathForCropCamera);
mCropOptions = cropOptions; Intent intent = Utils.makeCropIntentNoCovering(getContext(), srcFile, targetFile, mAuthority, getCropOptions(), mCropTitle);
mCropTitle = cropTitle;
try { try {
startActivityForResult(Utils.makeAlbumIntent(), REQUEST_ALBUM); startActivityForResult(intent, REQUEST_CROP);
return true; return true;
} catch (Exception e) { } catch (Exception e) {
return false; Log.e(TAG, "toCropPhotoFromAlbum error", e);
} }
return false;
} }
private boolean toCamera() { private boolean toCamera(String savePhotoPath) {
if (!Utils.hasCamera(getContext())) { if (!Utils.hasCamera(getContext())) {
return false; return false;
} }
File targetFile = new File(mSavePhotoPath); File targetFile = new File(savePhotoPath);
Intent intent = Utils.makeCaptureIntent(getContext(), targetFile, mAuthority); Intent intent = Utils.makeCaptureIntent(getContext(), targetFile, mAuthority);
try { try {
startActivityForResult(intent, REQUEST_CAMERA); startActivityForResult(intent, REQUEST_CAMERA);
@ -154,30 +158,50 @@ public class SystemMediaSelector {
return false; return false;
} }
private boolean toCrop() { ///////////////////////////////////////////////////////////////////////////
File targetFile = new File(mSavePhotoPath); // take photo from album
Intent intent = Utils.makeCropIntent(getContext(), targetFile, mAuthority, getCropOptions(), mCropTitle); ///////////////////////////////////////////////////////////////////////////
public boolean takePhotoFormAlbum() {
mNeedCrop = false;
try { try {
startActivityForResult(intent, REQUEST_CROP); startActivityForResult(Utils.makeAlbumIntent(), REQUEST_ALBUM);
return true; return true;
} catch (Exception e) { } catch (Exception e) {
Log.e(TAG, "toCrop error", e); return false;
}
}
public boolean takePhotoFormAlbumAndCrop(String savePhotoPath, @Nullable CropOptions cropOptions, String cropTitle) {
mNeedCrop = true;
mSavePhotoPath = savePhotoPath;
mCropOptions = cropOptions;
mCropTitle = cropTitle;
try {
startActivityForResult(Utils.makeAlbumIntent(), REQUEST_ALBUM);
return true;
} catch (Exception e) {
return false;
} }
return false;
} }
private boolean toCrop(Uri uri) { private boolean toCropPhotoFromAlbum(Uri uri) {
File targetFile = new File(mSavePhotoPath); File targetFile = new File(mSavePhotoPath);
Intent intent = Utils.makeCropIntent(getContext(), uri, targetFile, mAuthority, getCropOptions(), mCropTitle); File srcFile = new File(Utils.getAbsolutePath(getContext(), uri));
Intent intent = Utils.makeCropIntentNoCovering(getContext(), srcFile, targetFile, mAuthority, getCropOptions(), mCropTitle);
try { try {
startActivityForResult(intent, REQUEST_CROP); startActivityForResult(intent, REQUEST_CROP);
return true; return true;
} catch (Exception e) { } catch (Exception e) {
Log.e(TAG, "toCrop error", e); Log.e(TAG, "toCropPhotoFromAlbum error", e);
} }
return false; return false;
} }
///////////////////////////////////////////////////////////////////////////
// take photo from album
///////////////////////////////////////////////////////////////////////////
public boolean takeFile() { public boolean takeFile() {
return takeFile(null); return takeFile(null);
} }
@ -192,6 +216,7 @@ public class SystemMediaSelector {
} }
return true; return true;
} }
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// Process Result // Process Result
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
@ -205,6 +230,17 @@ public class SystemMediaSelector {
processAlbumResult(resultCode, data); processAlbumResult(resultCode, data);
} else if (requestCode == REQUEST_FILE) { } else if (requestCode == REQUEST_FILE) {
processFileResult(resultCode, data); processFileResult(resultCode, data);
} else if (requestCode == REQUEST_LINRARY_CROP) {
processUCropResult(data);
}
}
private void processUCropResult(Intent data) {
Uri uCropResult = Utils.getUCropResult(data);
if (uCropResult == null) {
mMediaSelectorCallback.onTakeFail();
} else {
mMediaSelectorCallback.onTakeSuccess(Utils.getAbsolutePath(getContext(), uCropResult));
} }
} }
@ -227,9 +263,13 @@ public class SystemMediaSelector {
if (data != null && data.getData() != null) { if (data != null && data.getData() != null) {
Uri uri = data.getData(); Uri uri = data.getData();
if (mNeedCrop) { if (mNeedCrop) {
boolean success = toCrop(uri); if (mUseInnerCrop) {
if (!success) { Utils.toUCrop(getContext(), mFragment, Utils.getAbsolutePath(getContext(), uri), mSavePhotoPath, getCropOptions(), REQUEST_LINRARY_CROP);
mMediaSelectorCallback.onTakeSuccess(Utils.getAbsolutePath(getContext(), uri)); } else {
boolean success = toCropPhotoFromAlbum(uri);
if (!success) {
mMediaSelectorCallback.onTakeSuccess(Utils.getAbsolutePath(getContext(), uri));
}
} }
} else { } else {
mMediaSelectorCallback.onTakeSuccess(Utils.getAbsolutePath(getContext(), uri)); mMediaSelectorCallback.onTakeSuccess(Utils.getAbsolutePath(getContext(), uri));
@ -260,18 +300,31 @@ public class SystemMediaSelector {
private void processCameraResult(int resultCode, @SuppressWarnings("unused") Intent data) { private void processCameraResult(int resultCode, @SuppressWarnings("unused") Intent data) {
if (resultCode == Activity.RESULT_OK) { if (resultCode == Activity.RESULT_OK) {
//检测图片是否被保存下来
if (!new File(mSavePhotoPath).exists()) {
mMediaSelectorCallback.onTakeFail();
return;
}
//需要裁减,可以裁减则进行裁减,否则直接返回 //需要裁减,可以裁减则进行裁减,否则直接返回
if (mNeedCrop) { if (mNeedCrop) {
boolean success = toCrop(); //检测图片是否被保存下来
if (!success) { File photoPath = new File(mSavePhotoPathForCropCamera);
mMediaSelectorCallback.onTakeSuccess(mSavePhotoPath); if (!photoPath.exists()) {
mMediaSelectorCallback.onTakeFail();
return;
} }
if (mUseInnerCrop) {
Utils.toUCrop(getContext(), mFragment, mSavePhotoPathForCropCamera, mSavePhotoPath, getCropOptions(), REQUEST_LINRARY_CROP);
} else {
boolean success = toCropPhotoFromCamera();
if (!success) {
photoPath.renameTo(new File(mSavePhotoPath));
mMediaSelectorCallback.onTakeSuccess(mSavePhotoPath);
}
}
} else { } else {
//检测图片是否被保存下来
if (!new File(mSavePhotoPath).exists()) {
mMediaSelectorCallback.onTakeFail();
return;
}
mMediaSelectorCallback.onTakeSuccess(mSavePhotoPath); mMediaSelectorCallback.onTakeSuccess(mSavePhotoPath);
} }
} }
@ -291,5 +344,4 @@ public class SystemMediaSelector {
} }
}
}

@ -16,13 +16,18 @@ import android.os.Environment;
import android.provider.DocumentsContract; import android.provider.DocumentsContract;
import android.provider.MediaStore; import android.provider.MediaStore;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log;
import com.yalantis.ucrop.UCrop;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.FileProvider; import androidx.core.content.FileProvider;
import androidx.fragment.app.Fragment;
/** /**
* See: * See:
@ -31,11 +36,13 @@ import androidx.core.content.FileProvider;
* </pre> * </pre>
* *
* @author Ztiany * @author Ztiany
* Email: ztiany3@gmail.com * Email: ztiany3@gmail.com
* Date : 2017-08-09 10:54 * Date : 2017-08-09 10:54
*/ */
final class Utils { final class Utils {
private static final String TAG = "Utils";
private Utils() { private Utils() {
throw new UnsupportedOperationException("Utils"); throw new UnsupportedOperationException("Utils");
} }
@ -93,9 +100,9 @@ final class Utils {
/** /**
* @param targetFile 源文件裁剪之后新的图片覆盖此文件 * @param targetFile 源文件裁剪之后新的图片覆盖此文件
*/ */
static Intent makeCropIntent(Context context, File targetFile, String authority, CropOptions cropOptions, String title) { static Intent makeCropIntentCovering(Context context, File targetFile, String authority, CropOptions cropOptions, String title) {
Log.d(TAG, "makeCropIntentCovering() called with: context = [" + context + "], targetFile = [" + targetFile + "], authority = [" + authority + "], cropOptions = [" + cropOptions + "], title = [" + title + "]");
makeFilePath(targetFile);
Intent intent = new Intent("com.android.camera.action.CROP"); Intent intent = new Intent("com.android.camera.action.CROP");
Uri fileUri; Uri fileUri;
@ -117,29 +124,43 @@ final class Utils {
intent.putExtra("return-data", false); intent.putExtra("return-data", false);
intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString()); intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
intent.putExtra("noFaceDetection", true); intent.putExtra("noFaceDetection", true);
List<ResolveInfo> resInfoList = context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
for (ResolveInfo resolveInfo : resInfoList) {
String packageName = resolveInfo.activityInfo.packageName;
context.grantUriPermission(packageName, fileUri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
intent = Intent.createChooser(intent, title); intent = Intent.createChooser(intent, title);
return intent; return intent;
} }
/** /**
* @param targetFile 目标文件裁剪之后新的图片保存到此文件 * @param targetFile 目标文件裁剪之后新的图片保存到此文件
* @param src 源文件 * @param srcFile 源文件
*/ */
static Intent makeCropIntent(Context context, Uri src, File targetFile, String authority, CropOptions cropOptions, String title) { static Intent makeCropIntentNoCovering(Context context, File srcFile, File targetFile, String authority, CropOptions cropOptions, String title) {
makeFilePath(targetFile);
Intent intent = new Intent("com.android.camera.action.CROP"); Intent intent = new Intent("com.android.camera.action.CROP");
intent.setDataAndType(src, "image/*");
Uri fileUri; Uri outputUri;
Uri srcUri;
if (Build.VERSION.SDK_INT < 24) { if (Build.VERSION.SDK_INT < 24) {
fileUri = Uri.fromFile(targetFile); outputUri = Uri.fromFile(targetFile);
srcUri = Uri.fromFile(srcFile);
} else { } else {
fileUri = FileProvider.getUriForFile(context, authority, targetFile); outputUri = FileProvider.getUriForFile(context, authority, targetFile);
srcUri = FileProvider.getUriForFile(context, authority, srcFile);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
} }
intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri); intent.setDataAndType(srcUri, "image/*");
intent.putExtra(MediaStore.EXTRA_OUTPUT, outputUri);
intent.putExtra("aspectX", cropOptions.getAspectX()); intent.putExtra("aspectX", cropOptions.getAspectX());
intent.putExtra("aspectY", cropOptions.getAspectY()); intent.putExtra("aspectY", cropOptions.getAspectY());
intent.putExtra("outputX", cropOptions.getOutputX()); intent.putExtra("outputX", cropOptions.getOutputX());
@ -148,22 +169,83 @@ final class Utils {
intent.putExtra("return-data", false); intent.putExtra("return-data", false);
intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString()); intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
intent.putExtra("noFaceDetection", true); intent.putExtra("noFaceDetection", true);
List<ResolveInfo> resInfoList = context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
for (ResolveInfo resolveInfo : resInfoList) {
String packageName = resolveInfo.activityInfo.packageName;
context.grantUriPermission(packageName, outputUri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
intent = Intent.createChooser(intent, title); intent = Intent.createChooser(intent, title);
return intent; return intent;
} }
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// Album // UCrop
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
static void toUCrop(Context context, Fragment fragment, String srcPath, String targetPath, CropOptions cropConfig, int requestCode) {
Uri srcUri = new Uri.Builder()
.scheme("file")
.appendPath(srcPath)
.build();
Uri targetUri = new Uri.Builder()
.scheme("file")
.appendPath(targetPath)
.build();
//参数
UCrop.Options crop = new UCrop.Options();
crop.setCompressionFormat(Bitmap.CompressFormat.JPEG);
crop.withMaxResultSize(cropConfig.getOutputX(), cropConfig.getAspectY());
crop.withAspectRatio(cropConfig.getAspectX(), cropConfig.getAspectY());
//颜色
int color = StyleUtils.fetchPrimaryColor(context);
crop.setToolbarColor(color);
crop.setStatusBarColor(color);
//开始裁减
if (fragment != null) {
UCrop.of(srcUri, targetUri)
.withOptions(crop)
.start(context, fragment, requestCode);
} else {
if (!(context instanceof AppCompatActivity)) {
throw new IllegalArgumentException("the context must be instance of AppCompatActivity");
}
UCrop.of(srcUri, targetUri)
.withOptions(crop)
.start((AppCompatActivity) context, requestCode);
}
}
public static Uri getUCropResult(Intent data) {
if (data == null) {
return null;
}
Throwable throwable = UCrop.getError(data);
if (throwable != null) {
return null;
}
return UCrop.getOutput(data);
}
///////////////////////////////////////////////////////////////////////////
// Album
///////////////////////////////////////////////////////////////////////////
static Intent makeAlbumIntent() { static Intent makeAlbumIntent() {
return new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI); return new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
} }
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// 从各种Uri中获取真实的路径 // 从各种Uri中获取真实的路径
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
/**
* @see "https://stackoverflow.com/questions/20067508/get-real-path-from-uri-android-kitkat-new-storage-access-framework/20559175"
*/
static String getAbsolutePath(final Context context, final Uri uri) { static String getAbsolutePath(final Context context, final Uri uri) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && DocumentsContract.isDocumentUri(context, uri)) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && DocumentsContract.isDocumentUri(context, uri)) {
// ExternalStorageProvider // ExternalStorageProvider
@ -213,14 +295,14 @@ final class Utils {
} }
/** /**
* Get the value of the data column for this Uri. This is useful for * Get the value of the data column for this Uri. This is useful for MediaStore Uris, and other file-based ContentProviders.
* MediaStore Uris, and other file-based ContentProviders.
* *
* @param context The context. * @param context The context.
* @param uri The Uri to query. * @param uri The Uri to query.
* @param selection (Optional) Filter used in the query. * @param selection (Optional) Filter used in the query.
* @param selectionArgs (Optional) Selection arguments used in the query. * @param selectionArgs (Optional) Selection arguments used in the query.
* @return The value of the _data column, which is typically a file path. * @return The value of the _data column, which is typically a file path.
* @see "https://stackoverflow.com/questions/20067508/get-real-path-from-uri-android-kitkat-new-storage-access-framework/20559175"
*/ */
private static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) { private static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) {
Cursor cursor = null; Cursor cursor = null;
@ -328,18 +410,6 @@ final class Utils {
return returnBm; return returnBm;
} }
///////////////////////////////////////////////////////////////////////////
// FileUtils
///////////////////////////////////////////////////////////////////////////
private static boolean makeFilePath(File file) {
if (file == null) {
return false;
}
File parent = file.getParentFile();
return parent.exists() || parent.mkdirs();
}
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
//如果照片保存的文件目录是由 getExternalFilesDir() 所提供的,那么,媒体扫描器是不能访问这些文件的,因为照片对于你的APP来说是私有的。 //如果照片保存的文件目录是由 getExternalFilesDir() 所提供的,那么,媒体扫描器是不能访问这些文件的,因为照片对于你的APP来说是私有的。
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
@ -366,4 +436,68 @@ final class Utils {
context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" + photoPath))); context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" + photoPath)));
} }
///////////////////////////////////////////////////////////////////////////
// FileUtils
///////////////////////////////////////////////////////////////////////////
private static boolean makeFilePath(File file) {
if (file == null) {
return false;
}
File parent = file.getParentFile();
if (parent == null) {
return false;
}
return parent.exists() || parent.mkdirs();
}
private static void makeNewFile(File file) {
makeFilePath(file);
try {
if (file.exists()) {
file.delete();
}
file.createNewFile();
} catch (Exception e) {
e.printStackTrace();
}
}
private static boolean isSpace(final String s) {
if (s == null) return true;
for (int i = 0, len = s.length(); i < len; ++i) {
if (!Character.isWhitespace(s.charAt(i))) {
return false;
}
}
return true;
}
public static String getFileNameNoExtension(final String filePath) {
if (isSpace(filePath)) return "";
int lastPoi = filePath.lastIndexOf('.');
int lastSep = filePath.lastIndexOf(File.separator);
if (lastSep == -1) {
return (lastPoi == -1 ? filePath : filePath.substring(0, lastPoi));
}
if (lastPoi == -1 || lastSep > lastPoi) {
return filePath.substring(lastSep + 1);
}
return filePath.substring(lastSep + 1, lastPoi);
}
public static String getFileExtension(final String filePath) {
if (isSpace(filePath)) return "";
int lastPoi = filePath.lastIndexOf('.');
int lastSep = filePath.lastIndexOf(File.separator);
if (lastPoi == -1 || lastSep >= lastPoi) return "";
return filePath.substring(lastPoi + 1);
}
public static String addFilePostfix(final String filePath, String postfix) {
if (isSpace(filePath)) return "";
File file = new File(filePath);
return file.getParentFile().getAbsolutePath() + File.separator + getFileNameNoExtension(filePath) + postfix + "." + getFileExtension(filePath);
}
} }
Loading…
Cancel
Save