可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
Pick image for crop from gallery and camera it's done for below Android 7.0 but in Android Nought it crashes in camera. I use fileprovider for it but doesn't work.
MainActivity.java
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Button mBtn;
private Context context;
private static final int SELECT_PICTURE_CAMARA = 101, SELECT_PICTURE = 201, CROP_IMAGE = 301;
private Uri outputFileUri;
String mCurrentPhotoPath;
private Uri selectedImageUri;
private File finalFile = null;
private ImageView imageView;
private PermissionUtil permissionUtil;
Uri fileUri;
File file = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mBtn = (Button) findViewById(R.id.btn_img);
imageView = (ImageView) findViewById(R.id.img_photo);
permissionUtil = new PermissionUtil();
mBtn.setOnClickListener(this);
context = this;
}
@Override
public void onClick(View view) {
selectImageOption();
}
private void selectImageOption() {
final CharSequence[] items = {"Capture Photo", "Choose from Gallery", "Cancel"};
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder.setTitle("Add Photo!");
builder.setItems(items, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int item) {
if (items[item].equals("Capture Photo")) {
if (permissionUtil.checkMarshMellowPermission()) {
if (permissionUtil.verifyPermissions(MainActivity.this, permissionUtil.getCameraPermissions()))
onClickCamera();
else
ActivityCompat.requestPermissions(MainActivity.this, permissionUtil.getCameraPermissions(), SELECT_PICTURE_CAMARA);
} else
onClickCamera();
} else if (items[item].equals("Choose from Gallery")) {
if (permissionUtil.checkMarshMellowPermission()) {
if (permissionUtil.verifyPermissions(MainActivity.this, permissionUtil.getGalleryPermissions()))
onClickGallery();
else
ActivityCompat.requestPermissions(MainActivity.this, permissionUtil.getGalleryPermissions(), SELECT_PICTURE);
} else
onClickGallery();
} else if (items[item].equals("Cancel")) {
dialog.dismiss();
}
}
});
builder.show();
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
if (requestCode == SELECT_PICTURE) {
selectedImageUri = data.getData();
cropImage(selectedImageUri);
} else if (requestCode == CROP_IMAGE) {
Uri imageUri = Uri.parse(mCurrentPhotoPath);
File file = new File(imageUri.getPath());
try {
InputStream ims = new FileInputStream(file);
imageView.setImageBitmap(BitmapFactory.decodeStream(ims));
} catch (FileNotFoundException e) {
return;
}
} else if (requestCode == SELECT_PICTURE_CAMARA && resultCode == Activity.RESULT_OK) {
cropImage1();
}
}
}
private void onClickCamera() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(context.getPackageManager()) != null) {
/* File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException ex) {
}
if (photoFile != null) {
Uri photoURI;
if (Build.VERSION.SDK_INT >= 24) {
photoURI = FileProvider.getUriForFile(MainActivity.this,
BuildConfig.APPLICATION_ID + ".fileprovider", photoFile);
} else {
photoURI = Uri.fromFile(photoFile);
}
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(takePictureIntent, SELECT_PICTURE_CAMARA);
}*/
ContentValues values = new ContentValues(1);
values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpg");
fileUri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
takePictureIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
startActivityForResult(takePictureIntent, SELECT_PICTURE_CAMARA);
} else {
Toast.makeText(this, getString(R.string.error_no_camera), Toast.LENGTH_LONG).show();
}
}
private void onClickGallery() {
List<Intent> targets = new ArrayList<>();
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_PICK);
intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
List<ResolveInfo> candidates = getApplicationContext().getPackageManager().queryIntentActivities(intent, 0);
for (ResolveInfo candidate : candidates) {
String packageName = candidate.activityInfo.packageName;
if (!packageName.equals("com.google.android.apps.photos") && !packageName.equals("com.google.android.apps.plus") && !packageName.equals("com.android.documentsui")) {
Intent iWantThis = new Intent();
iWantThis.setType("image/*");
iWantThis.setAction(Intent.ACTION_PICK);
iWantThis.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
iWantThis.setPackage(packageName);
targets.add(iWantThis);
}
}
if (targets.size() > 0) {
Intent chooser = Intent.createChooser(targets.remove(0), "Select Picture");
chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, targets.toArray(new Parcelable[targets.size()]));
startActivityForResult(chooser, SELECT_PICTURE);
} else {
Intent intent1 = new Intent(Intent.ACTION_PICK);
intent1.setType("image/*");
startActivityForResult(Intent.createChooser(intent1, "Select Picture"), SELECT_PICTURE);
}
}
private File createImageFile() throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
// Save a file: path for use with ACTION_VIEW intents
if (Build.VERSION.SDK_INT >= 24) {
mCurrentPhotoPath = String.valueOf(FileProvider.getUriForFile(MainActivity.this,
BuildConfig.APPLICATION_ID + ".provider", image));
} else {
mCurrentPhotoPath = String.valueOf(Uri.fromFile(image));
}
return image;
}
/*private Uri createImageUri(){
ContentResolver contentResolver=getContentResolver();
ContentValues cv=new ContentValues();
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
cv.put(MediaStore.Images.Media.TITLE,timeStamp);
return contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,cv);
}*/
private void cropImage(Uri selectedImageUri) {
Intent cropIntent = new Intent("com.android.camera.action.CROP");
cropIntent.setDataAndType(selectedImageUri, "image/*");
cropIntent.putExtra("crop", "true");
cropIntent.putExtra("aspectX", 1);
cropIntent.putExtra("aspectY", 1.5);
cropIntent.putExtra("return-data", true);
outputFileUri = Uri.fromFile(createCropFile());
cropIntent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
startActivityForResult(cropIntent, CROP_IMAGE);
}
private void cropImage1() {
Intent cropIntent = new Intent("com.android.camera.action.CROP");
cropIntent.setDataAndType(fileUri, "image/*");
cropIntent.putExtra("crop", "true");
cropIntent.putExtra("aspectX", 1);
cropIntent.putExtra("aspectY", 1.5);
cropIntent.putExtra("return-data", true);
if (Build.VERSION.SDK_INT >= 24) {
outputFileUri = FileProvider.getUriForFile(MainActivity.this,
BuildConfig.APPLICATION_ID + ".provider", createCropFile());
} else
outputFileUri = Uri.fromFile(createCropFile());
cropIntent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
startActivityForResult(cropIntent, CROP_IMAGE);
/* ContentValues values = new ContentValues(1);
values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpg");
outputFileUri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
cropIntent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
cropIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
cropIntent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
startActivityForResult(cropIntent, CROP_IMAGE);*/
}
private File createCropFile() {
File storageDir = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
// path = path + (timeStamp + "1jpg");
try {
file = File.createTempFile(timeStamp, ".jpg", storageDir);
} catch (IOException e) {
e.printStackTrace();
}
/*if (Build.VERSION.SDK_INT >= 24)
mCurrentPhotoPath = String.valueOf(FileProvider.getUriForFile(MainActivity.this,
BuildConfig.APPLICATION_ID + ".provider", file));
else*/
mCurrentPhotoPath = String.valueOf(Uri.fromFile(file));
return file;
}
}
this work in all device but not in >= android 7.0 Nought device
回答1:
I just solve this problem on Nexus6p android N,you need grant permission to uri so the system camera can access the file wait crop temporarily,because of StrictMode Android N has do not support pass a file:Uri in an Intent extra anymore see Scheme Ban in N Developer Preview,we use FileProvider
instead.here is my source code:
AndroidManifest.xml
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="dreamgo.corp.provider"
android:grantUriPermissions="true"
android:exported="false">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/filepaths"/>
</provider>
filepaths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="images" path="."/>
</paths>
MainActivity.java
Uri photoURI = FileProvider.getUriForFile(context, "dreamgo.corp.provider", file);
//grant uri with essential permission the first arg is the The packagename you would like to allow to access the Uri.
context.grantUriPermission("com.android.camera",photoURI,
Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
Intent intent = new Intent("com.android.camera.action.CROP");
intent.setDataAndType(photoURI, "image/*");
//you must setup two line below
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
intent.putExtra("crop", "true");
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 1);
intent.putExtra("outputX", 200);
intent.putExtra("outputY", 200);
intent.putExtra("return-data", true);
//you must setup this
intent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(intent, 1);
回答2:
I got the solution.Posting my answer.
In MainActivity.java
public class MainActivity extends AppCompatActivity {
@BindView(R.id.img_camera)
CircleImageView mImgCamera;
private ChoosePhoto choosePhoto=null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
}
@OnClick(R.id.img_camera)
public void onViewClicked() {
choosePhoto = new ChoosePhoto(this);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == Activity.RESULT_OK) {
if (requestCode == ChoosePhoto.CHOOSE_PHOTO_INTENT) {
if (data != null && data.getData() != null) {
choosePhoto.handleGalleryResult(data);
} else {
choosePhoto.handleCameraResult(choosePhoto.getCameraUri());
}
}else if (requestCode == ChoosePhoto.SELECTED_IMG_CROP) {
mImgCamera.setImageURI(choosePhoto.getCropImageUrl());
}
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == ChoosePhoto.SELECT_PICTURE_CAMERA) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
choosePhoto.showAlertDialog();
}
}
}
ChoosePhoto.java
public class ChoosePhoto {
public static int CHOOSE_PHOTO_INTENT = 101;
public static int SELECTED_IMG_CROP = 102;
public static int SELECT_PICTURE_CAMERA = 103;
public static int currentAndroidDeviceVersion = Build.VERSION.SDK_INT;
private int ASPECT_X = 1;
private int ASPECT_Y = 1;
private int OUT_PUT_X = 300;
private int OUT_PUT_Y = 300;
private boolean SCALE = true;
private Uri cropPictureUrl, selectedImageUri = null, cameraUrl = null;
private Context mContext;
public ChoosePhoto(Context context) {
mContext = context;
init();
}
private void init() {
PermissionUtil permissionUtil = new PermissionUtil();
if (permissionUtil.checkMarshMellowPermission()) {
if (permissionUtil.verifyPermissions(mContext, permissionUtil.getCameraPermissions()) && permissionUtil.verifyPermissions(mContext, permissionUtil.getGalleryPermissions()))
showAlertDialog();
else {
ActivityCompat.requestPermissions((Activity) mContext, permissionUtil.getCameraPermissions(), SELECT_PICTURE_CAMERA);
}
} else {
showAlertDialog();
}
}
public void showAlertDialog() {
final Intent galleryIntent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
galleryIntent.setType("image/*");
cameraUrl = FileUtil.getInstance(mContext).createImageUri();
//Create any other intents you want
final Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
cameraIntent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, cameraUrl);
//Add them to an intent array
Intent[] intents = new Intent[]{cameraIntent};
//Create a choose from your first intent then pass in the intent array
final Intent chooserIntent = Intent.createChooser(galleryIntent, mContext.getString(R.string.choose_photo_title));
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intents);
((Activity) mContext).startActivityForResult(chooserIntent, CHOOSE_PHOTO_INTENT);
}
// Change this method(edited)
public void handleGalleryResult(Intent data) {
try {
cropPictureUrl = Uri.fromFile(FileUtil.getInstance(mContext)
.createImageTempFile(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)));
String realPathFromURI = FileUtil.getRealPathFromURI(mContext, data.getData());
File file = new File(realPathFromURI == null ? getImageUrlWithAuthority(mContext, data.getData()) : realPathFromURI);
if (file.exists()) {
if (currentAndroidDeviceVersion > 23) {
cropImage(FileProvider.getUriForFile(mContext, mContext.getApplicationContext().getPackageName() + ".provider", file), cropPictureUrl);
} else {
cropImage(Uri.fromFile(file), cropPictureUrl);
}
} else {
cropImage(data.getData(), cropPictureUrl);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static String getImageUrlWithAuthority(Context context, Uri uri) {
InputStream is = null;
if (uri.getAuthority() != null) {
try {
is = context.getContentResolver().openInputStream(uri);
Bitmap bmp = BitmapFactory.decodeStream(is);
return writeToTempImageAndGetPathUri(context, bmp).toString();
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
public static Uri writeToTempImageAndGetPathUri(Context inContext, Bitmap inImage) {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
inImage.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
String path = MediaStore.Images.Media.insertImage(inContext.getContentResolver(), inImage, "Title", null);
return Uri.parse(path);
}
public void handleCameraResult(Uri cameraPictureUrl) {
try {
cropPictureUrl = Uri.fromFile(FileUtil.getInstance(mContext)
.createImageTempFile(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)));
cropImage(cameraPictureUrl, cropPictureUrl);
} catch (IOException e) {
e.printStackTrace();
}
}
public Uri getCameraUri() {
return cameraUrl;
}
public Uri getCropImageUrl() {
return selectedImageUri;
}
private void cropImage(final Uri sourceImage, Uri destinationImage) {
Intent intent = new Intent("com.android.camera.action.CROP");
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
intent.setType("image/*");
List<ResolveInfo> list = mContext.getPackageManager().queryIntentActivities(intent, 0);
int size = list.size();
if (size == 0) {
//Utils.showToast(mContext, mContext.getString(R.string.error_cant_select_cropping_app));
selectedImageUri = sourceImage;
intent.putExtra(MediaStore.EXTRA_OUTPUT, sourceImage);
((Activity) mContext).startActivityForResult(intent, SELECTED_IMG_CROP);
return;
} else {
intent.setDataAndType(sourceImage, "image/*");
intent.putExtra("aspectX", ASPECT_X);
intent.putExtra("aspectY", ASPECT_Y);
intent.putExtra("outputY", OUT_PUT_Y);
intent.putExtra("outputX", OUT_PUT_X);
intent.putExtra("scale", SCALE);
//intent.putExtra("return-data", true);
intent.putExtra(MediaStore.EXTRA_OUTPUT, destinationImage);
selectedImageUri = destinationImage;
if (size == 1) {
Intent i = new Intent(intent);
ResolveInfo res = list.get(0);
i.setComponent(new ComponentName(res.activityInfo.packageName, res.activityInfo.name));
((Activity) mContext).startActivityForResult(intent, SELECTED_IMG_CROP);
} else {
Intent i = new Intent(intent);
i.putExtra(Intent.EXTRA_INITIAL_INTENTS, list.toArray(new Parcelable[list.size()]));
((Activity) mContext).startActivityForResult(intent, SELECTED_IMG_CROP);
}
}
}
}
FileUtil.java
public class FileUtil {
private static FileUtil sSingleton;
private Context context;
private FileUtil(Context ctx) {
context = ctx;
}
/**
* Gets instance.
*
* @param ctx the ctx
* @return the instance
*/
public static FileUtil getInstance(Context ctx) {
if (sSingleton == null) {
synchronized (FileUtil.class) {
sSingleton = new FileUtil(ctx);
}
}
return sSingleton;
}
public Uri createImageUri() {
ContentResolver contentResolver = context.getContentResolver();
ContentValues cv = new ContentValues();
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date());
cv.put(MediaStore.Images.Media.TITLE, timeStamp);
return contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, cv);
}
/**
* Create image temp file file.
*
* @param filePathDir the file path dir
* @return the file
* @throws IOException the io exception
*/
@SuppressLint("SimpleDateFormat")
public File createImageTempFile(File filePathDir) throws IOException {
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
return File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
filePathDir /* directory */
);
}
public static String getUploadFileName() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss", Locale.US);
Date date = new Date();
return String.format("profile_%s.png", sdf.format(date));
}
//add this code(edited)
//get Path
@TargetApi(Build.VERSION_CODES.KITKAT)
public static String getRealPathFromURI(Context context, final Uri uri) {
final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
// DocumentProvider
if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
// ExternalStorageProvider
if (isExternalStorageDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
if ("primary".equalsIgnoreCase(type)) {
return Environment.getExternalStorageDirectory() + "/" + split[1];
}
}
// DownloadsProvider
else if (isDownloadsDocument(uri)) {
final String id = DocumentsContract.getDocumentId(uri);
final Uri contentUri = ContentUris.withAppendedId(
Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
return getDataColumn(context, contentUri, null, null);
}
// MediaProvider
else if (isMediaDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final 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;
}
final String selection = "_id=?";
final String[] selectionArgs = new String[]{
split[1]
};
return getDataColumn(context, contentUri, selection, selectionArgs);
}
}
// MediaStore (and general)
else if ("content".equalsIgnoreCase(uri.getScheme())) {
// Return the remote address
if (isGooglePhotosUri(uri))
return uri.getLastPathSegment();
return getDataColumn(context, uri, null, null);
}
// File
else if ("file".equalsIgnoreCase(uri.getScheme())) {
return uri.getPath();
} else
return getRealPathFromURIDB(uri);
return null;
}
/**
* Gets real path from uri.
*
* @param contentUri the content uri
* @return the real path from uri
*/
private static String getRealPathFromURIDB(Uri contentUri) {
Cursor cursor = context.getContentResolver().query(contentUri, null, null, null, null);
if (cursor == null) {
return contentUri.getPath();
} else {
cursor.moveToFirst();
int index = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
String realPath = cursor.getString(index);
cursor.close();
return realPath;
}
}
/**
* Gets data column.
*
* @param uri the uri
* @param selection the selection
* @param selectionArgs the selection args
* @return the data column
*/
public static 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 index = cursor.getColumnIndexOrThrow(column);
return cursor.getString(index);
}
} finally {
if (cursor != null)
cursor.close();
}
return null;
}
/**
* Is external storage document boolean.
*
* @param uri The Uri to check.
* @return Whether the Uri authority is ExternalStorageProvider.
*/
public static boolean isExternalStorageDocument(Uri uri) {
return "com.android.externalstorage.documents".equals(uri.getAuthority());
}
/**
* Is downloads document boolean.
*
* @param uri The Uri to check.
* @return Whether the Uri authority is DownloadsProvider.
*/
public static boolean isDownloadsDocument(Uri uri) {
return "com.android.providers.downloads.documents".equals(uri.getAuthority());
}
/**
* Is media document boolean.
*
* @param uri The Uri to check.
* @return Whether the Uri authority is MediaProvider.
*/
public static boolean isMediaDocument(Uri uri) {
return "com.android.providers.media.documents".equals(uri.getAuthority());
}
/**
* Is google photos uri boolean.
*
* @param uri The Uri to check.
* @return Whether the Uri authority is Google Photos.
*/
public static boolean isGooglePhotosUri(Uri uri) {
return "com.google.android.apps.photos.content".equals(uri.getAuthority());
}
}
PermissionUtil.java
public class PermissionUtil {
private String[] galleryPermissions = {
"android.permission.WRITE_EXTERNAL_STORAGE",
"android.permission.READ_EXTERNAL_STORAGE"
};
private String[] cameraPermissions = {
"android.permission.CAMERA",
"android.permission.WRITE_EXTERNAL_STORAGE",
"android.permission.READ_EXTERNAL_STORAGE"
};
public String[] getGalleryPermissions(){
return galleryPermissions;
}
public String[] getCameraPermissions() {
return cameraPermissions;
}
public boolean verifyPermissions(Context context, String[] grantResults) {
for (String result : grantResults) {
if (ActivityCompat.checkSelfPermission(context, result) != PackageManager.PERMISSION_GRANTED) {
return false;
}
}
return true;
}
public boolean checkMarshMellowPermission(){
return(Build.VERSION.SDK_INT> Build.VERSION_CODES.LOLLIPOP_MR1);
}
public static void showPermissionDialog(Context mContext,String msg){
AlertDialog.Builder builder = new AlertDialog.Builder(mContext, R.style.DatePicker);
builder.setTitle("Need Permission");
builder.setMessage(msg);
builder.setPositiveButton(mContext.getString(R.string.invitation_yes), (dialogInterface, i) -> {
dialogInterface.dismiss();
Intent intent = new Intent();
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", mContext.getPackageName(), null);
intent.setData(uri);
(mContext).startActivity(intent);
});
builder.setNegativeButton(mContext.getString(R.string.invitation_del_no), (dialogInterface, i) -> {
dialogInterface.dismiss();
});
builder.show();
}
}
provide_paths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_files" path="."/>
</paths>
回答3:
I have two source for crop,one is gallery and the other one is camera
the method gallery:
//take a photo from gallery
public void gallery() {
//set UUID to filename
String PHOTO_FILE_NAME = UUID.randomUUID().toString()+".jpg";
Utils.putValue(this, Constants.UserPortraitFilePath,PHOTO_FILE_NAME);
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType("image/*");
startActivityForResult(intent, PHOTO_REQUEST_GALLERY);
}
the method camera:
//take a photo from camera
public void camera() {
//check sdcard is usable or not
if (Utils.hasSdcard()) {
//set UUID to filename
String PHOTO_FILE_NAME = UUID.randomUUID().toString()+".jpg";
Utils.putValue(this,Constants.UserPortraitFilePath,PHOTO_FILE_NAME);
Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
//set file location to DreamGo/Image
File path = Environment.getExternalStorageDirectory();
File dir = new File(path, "DreamGo/Image");
if(!dir.exists())
dir.mkdirs();
//Android N need use FileProvider get file
//uri because StrictMode System
//getUriForFile(content,provider author,file)
Uri photoURI = FileProvider.getUriForFile(context, "dream.go.provider",
new File(dir.getAbsolutePath(), PHOTO_FILE_NAME));
intent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(intent, PHOTO_REQUEST_CAMERA);
}else {
showToast("no storage device");
}
}
the crop method:
//Android N crop image
public void crop(Uri uri) {
context.grantUriPermission("com.android.camera",uri,
Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
Intent intent = new Intent("com.android.camera.action.CROP");
intent.setDataAndType(uri, "image/*");
//Android N need set permission to uri otherwise system camera don't has permission to access file wait crop
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
intent.putExtra("crop", "true");
//The proportion of the crop box is 1:1
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 1);
//Crop the output image size
intent.putExtra("outputX", 800);
intent.putExtra("outputY", 800);
//image type
intent.putExtra("outputFormat", "JPEG");
intent.putExtra("noFaceDetection", true);
//true - don't return uri | false - return uri
intent.putExtra("return-data", true);
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
startActivityForResult(intent, PHOTO_REQUEST_CUT);
}
the onActivityResult method :
private static final int PHOTO_REQUEST_CAMERA = 0;//camera
private static final int PHOTO_REQUEST_GALLERY = 1;//gallery
private static final int PHOTO_REQUEST_CUT = 2;//image crop
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
String PHOTO_FILE_NAME = Utils.getValue(this, Constants.UserPortraitFilePath);
File path = Environment.getExternalStorageDirectory();
File dir = new File(path, "DreamGo/Image");
if(!dir.exists())
dir.mkdirs();
switch (requestCode)
{
case PHOTO_REQUEST_GALLERY:
if (data != null){
//file from gallery
File sourceFile = new File(getRealPathFromURI(data.getData()));
//blank file DreamGo/Image/uuid.jpg
File destFile = new File(dir.getAbsolutePath(), PHOTO_FILE_NAME);
Log.e("photo",data.getData().getPath());
try {
//copy file from gallery to DreamGo/Image/uuid.jpg
// otherwise crop method can't cut image without write permission
copyFile(sourceFile,destFile);
//Android N need use FileProvider to get file uri
Uri photoURI = FileProvider.getUriForFile(context, "dream.go.provider", destFile);
//cut image
crop(photoURI);
} catch (IOException e) {
e.printStackTrace();
}
}
break;
case PHOTO_REQUEST_CAMERA:
//whether sdcard is usable has been checked before use camera
File tempFile = new File(dir.getAbsolutePath(), PHOTO_FILE_NAME);
Uri photoURI = FileProvider.getUriForFile(context, "dream.go.provider", tempFile);
crop(photoURI);
break;
case PHOTO_REQUEST_CUT:
try {
if(data!=null) {
file = new File(dir.getAbsolutePath(), PHOTO_FILE_NAME);
icon.loadImage("file://" + file.getAbsolutePath());
}else {
showToast("a error happened when cut picture");
}
} catch (Exception e) {
e.printStackTrace();
}
break;
default:
break;
}
}
the realted code:
//copy sourceFile to destFile
public void copyFile(File sourceFile, File destFile) throws IOException {
if (!sourceFile.exists()) {
return;
}
FileChannel source = new FileInputStream(sourceFile).getChannel();
FileChannel destination = new FileOutputStream(destFile).getChannel();
if (destination != null && source != null) {
destination.transferFrom(source, 0, source.size());
}
if (source != null) {
source.close();
}
if (destination != null) {
destination.close();
}
}
//file uri to real location in filesystem
public String getRealPathFromURI(Uri contentURI) {
Cursor cursor = getContentResolver().query(contentURI, null, null, null, null);
if (cursor == null) {
// Source is Dropbox or other similar local file path
return contentURI.getPath();
} else {
cursor.moveToFirst();
int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
return cursor.getString(idx);
}
}
public static final String getValue(Context context, String key) {
return getSharedPreference(context).getString(key, "");
}
public static final boolean putValue(Context context, String key,
String value) {
value = value == null ? "" : value;
SharedPreferences.Editor editor = getSharedPreference(context).edit();
editor.putString(key, value);
boolean result = editor.commit();
if (!result) {
return false;
}
return true;
}
回答4:
Have you added this in Manifest.xml??
<application
........
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/>
</provider>
</application>
this has to be there in your manifest.. for effect in the naugut android 7.0.
Again you need to add provider_paths.xml file in xml.
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_files" path="."/>
</paths>
回答5:
Uri uri = FileProvider.getUriForFile(this, getPackageName() + Configs.FILE_PROVIDER_NAME, inFile);
Intent intent = new Intent("com.android.camera.action.CROP");
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
intent.setDataAndType(uri, "image/*");
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(outFile));
You should notice that the uri for EXTRA_OUTPUT should not be modified by FileProvider.
And your paths.xml should like this
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_sd" path="."/>
<external-files-path name="external_app" path="."/>
<files-path name="files" path="."/>
<cache-path name="cache" path="."/>
Because you create crop file under getExternalFilesDir. So <external-files-path>
is necessary.
回答6:
Following solution works for me. I've tested with Gallery, Google drive, Photos etc.
Sample is in Kotlin
language.
ImagePickUtils.kt
fun getImageUri(context: Context, contentURI: String): Uri {
var conUri = Uri.parse(contentURI)
var filePath = ""
if (DocumentsContract.isDocumentUri(context, conUri)) {
val wholeID = DocumentsContract.getDocumentId(conUri)
// Split at colon, use second item in the array
val id = wholeID.split(":".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()[1]
val column = arrayOf(MediaStore.Images.Media.DATA)
// where id is equal to
val sel = MediaStore.Images.Media._ID + "=?"
val cursor = context.contentResolver.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
column, sel, arrayOf(id), null) ?: return conUri
val columnIndex = cursor.getColumnIndex(column[0])
if (cursor.moveToFirst()) {
filePath = cursor.getString(columnIndex)
}
cursor.close()
if (filePath.isNotEmpty()) {
filePath = filePath.replace(" ".toRegex(), "%20")
conUri = Uri.parse("file://$filePath")
}
}
return conUri
}
onActivityResult of Activity / Fragment:
if (data != null) {
val imagePath: Uri
if (data.data != null) {
val mImageUri = data.data
imagePath = getImageUri(this@HomeActivity, mImageUri.toString())
Log.i(TAG+" Image actual path", imagePath.toString())
}
}
Hope this would help you.
回答7:
Intent pickImageIntent = new Intent("com.android.camera.action.CROP");
Uri contentUri = imageUri;
pickImageIntent.setDataAndType(contentUri, "image/*");
pickImageIntent.putExtra("crop", "true");
pickImageIntent.putExtra("aspectX", 1);
pickImageIntent.putExtra("aspectY", 1);
pickImageIntent.putExtra("outputX", 400);
pickImageIntent.putExtra("outputY", 400);
pickImageIntent.putExtra("return-data", true);
startActivityForResult(pickImageIntent, RESULT_CROP);