java.lang.SecurityException: Permission Denial: writing android.support.v4.content.FileProvider uri
up vote
0
down vote
favorite
I am trying to use camera and save image. Followed the steps as commonsware suggested. Constantly I am getting error -
2018-11-12 02:10:54.588 3145-3173/com.bisw.weac E/DatabaseUtils: Writing exception to parcel
java.lang.SecurityException: Permission Denial: writing android.support.v4.content.FileProvider uri content://com.bisw.weac.provider/external_files/Android/data/com.bisw.weac/files/wallpaper/theme.jpg from pid=5566, uid=10071 requires the provider be exported, or grantUriPermission()
at android.content.ContentProvider.enforceWritePermissionInner(ContentProvider.java:713)
at android.content.ContentProvider$Transport.enforceWritePermission(ContentProvider.java:519)
at android.content.ContentProvider$Transport.enforceFilePermission(ContentProvider.java:491)
at android.content.ContentProvider$Transport.openAssetFile(ContentProvider.java:389)
at android.content.ContentProviderNative.onTransact(ContentProviderNative.java:251)
at android.os.Binder.execTransact(Binder.java:682)
I have tried almost everything like - intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
but nothing helps. I am croping the image from camera.
Activity code
public class LocalAlbumActivity extends BaseActivity implements View.OnClickListener
private static final int REQUEST_IMAGE_CAPTURE_THEME = 1;
private static final int REQUEST_IMAGE_CAPTURE_QRCODE_LOGO = 4;
private static final int REQUEST_IMAGE_CROP_THEME = 2;
private static final int REQUEST_IMAGE_CROP_QRCODE_LOGO = 5;
private static final int REQUEST_ALBUM_DETAIL = 3;
public static final String ALBUM_PATH = "album_path";
public static final String ALBUM_NAME = "album_name";
private LocalAlbumAdapter mLocalAlbumAdapter;
private List<ImageBucket> mLocalAlbumList;
private AsyncTask<Void, Void, List<ImageBucket>> mBucketLoadTask;
private ListView mLocalAlbumListView;
/**
* 访问本地相册类型:0,主题;1,扫码;2,造码
*/
private int mRequestType;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
OttoAppConfig.getInstance().register(this);
setContentView(R.layout.activity_local_album);
ViewGroup backGround = (ViewGroup) findViewById(R.id.background);
MyUtil.setBackgroundBlur(backGround, this);
initAdapter();
assignViews();
private void initAdapter()
mLocalAlbumList = new ArrayList<>();
mLocalAlbumAdapter = new LocalAlbumAdapter(this, mLocalAlbumList);
//trying permission
mBucketLoadTask = new AsyncTask<Void, Void, List<ImageBucket>>()
@Override
protected void onPreExecute()
super.onPreExecute();
// showLoading();
@Override
protected List<ImageBucket> doInBackground(Void... params)
return LocalAlbumImagePickerHelper.getInstance(LocalAlbumActivity.this)
.getImagesBucketList();
@Override
protected void onPostExecute(List<ImageBucket> list)
dismissLoadingDialog();
TextView emptyView = (TextView) findViewById(R.id.local_album_lv_empty);
mLocalAlbumListView.setEmptyView(emptyView);
mLocalAlbumList.addAll(list);
mLocalAlbumAdapter.notifyDataSetChanged();
;
mBucketLoadTask.execute();
private void dismissLoadingDialog()
ViewGroup progressBarLlyt = (ViewGroup) findViewById(R.id.progress_bar_llyt);
progressBarLlyt.setVisibility(View.GONE);
private void assignViews()
TextView loadingMsg = (TextView) findViewById(R.id.loading_msg);
loadingMsg.setText(R.string.scanning);
ImageView backBtn = (ImageView) findViewById(R.id.action_back);
TextView captureBtn = (TextView) findViewById(R.id.action_capture);
backBtn.setOnClickListener(this);
mRequestType = getIntent().getIntExtra(WeacConstants.REQUEST_LOCAL_ALBUM_TYPE, 0);
switch (mRequestType)
// 主题
case 0:
// 造码
case 2:
captureBtn.setOnClickListener(this);
break;
// 扫码
case 1:
// 隐藏拍照按钮
captureBtn.setVisibility(View.GONE);
break;
mLocalAlbumListView = (ListView) findViewById(R.id.local_album_lv);
mLocalAlbumListView.setAdapter(mLocalAlbumAdapter);
mLocalAlbumListView.setOnItemClickListener(new AdapterView.OnItemClickListener()
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
if (MyUtil.isFastDoubleClick())
return;
Intent intent = new Intent(LocalAlbumActivity.this, LocalAlbumDetailActivity.class);
intent.putParcelableArrayListExtra(ALBUM_PATH,
mLocalAlbumAdapter.getItem(position).bucketList);
intent.putExtra(ALBUM_NAME, mLocalAlbumAdapter.getItem(position).bucketName);
intent.putExtra(WeacConstants.REQUEST_LOCAL_ALBUM_TYPE, mRequestType);
startActivityForResult(intent, REQUEST_ALBUM_DETAIL);
);
// OverScrollDecoratorHelper.setUpOverScroll(mLocalAlbumListView);
private Uri mImageUri;
@Override
public void onClick(View v)
switch (v.getId())
// 返回
case R.id.action_back:
myFinish();
break;
// 拍照
case R.id.action_capture:
PackageManager pm = getPackageManager();
// FEATURE_CAMERA - 后置相机
// FEATURE_CAMERA_FRONT - 前置相机
if (pm.hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY)) Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.putExtra(MediaStore.EXTRA_OUTPUT, mImageUri);
startActivityForResult(intent, requestType);
overridePendingTransition(0, R.anim.zoomin);
else // 没有可用相机
Intent intent = new Intent(this, MyDialogActivitySingle.class);
intent.putExtra(WeacConstants.TITLE, getString(R.string.prompt));
intent.putExtra(WeacConstants.DETAIL, getString(R.string.camera_error));
startActivity(intent);
break;
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
super.onActivityResult(requestCode, resultCode, data);
if (resultCode != RESULT_OK)
// 截图/相机返回
overridePendingTransition(0, R.anim.zoomout);
return;
// 扫描二维码相册详细取消
if (data != null)
boolean isFinishMe = data.getBooleanExtra(LocalAlbumDetailActivity.FINISH_ACTIVITY, false);
if (isFinishMe && !isFinishing())
myFinish2();
return;
switch (requestCode)
// 拍照(截取主题壁纸)
case REQUEST_IMAGE_CAPTURE_THEME:
cropImage(0, REQUEST_IMAGE_CROP_THEME, WeacConstants.DIY_WALLPAPER_PATH);
break;
// 拍照(截取二维码logo)
case REQUEST_IMAGE_CAPTURE_QRCODE_LOGO:
cropImage(1, REQUEST_IMAGE_CROP_QRCODE_LOGO, WeacConstants.DIY_QRCODE_LOGO_PATH);
break;
// 截图(截取主题壁纸)
case REQUEST_IMAGE_CROP_THEME:
String filePath = MyUtil.getFilePath(this, WeacConstants.DIY_WALLPAPER_PATH);
// 更新壁纸信息
MyUtil.saveWallpaper(this, WeacConstants.WALLPAPER_PATH, filePath);
// 发送壁纸更新事件
OttoAppConfig.getInstance().post(new WallpaperEvent());
myFinish();
break;
// 截图(截取二维码logo)
case REQUEST_IMAGE_CROP_QRCODE_LOGO:
String logoPath = MyUtil.getFilePath(this, WeacConstants.DIY_QRCODE_LOGO_PATH);
// 保存自定义二维码logo地址
MyUtil.saveQRcodeLogoPath(this, logoPath);
// 发送自定义二维码logo截取地址事件
OttoAppConfig.getInstance().post(new QRcodeLogoEvent(logoPath));
myFinish();
break;
// 相册详细图片
case REQUEST_ALBUM_DETAIL:
assert data != null;
String url = data.getStringExtra(WeacConstants.IMAGE_URL);
OttoAppConfig.getInstance().post(new ScanCodeEvent(url));
myFinish2();
break;
private void cropImage(int type, int requestType, String path)
ToastUtil.showLongToast(this, "path:"+path);
Intent intent = MyUtil.getCropImageOptions(this, mImageUri, path, type);
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
if (intent.resolveActivity(getPackageManager()) != null)
startActivityForResult(intent, requestType);
overridePendingTransition(0, 0);
else
// 不可以复制其他应用的内部文件
// TODO: 全屏裁剪&自定义裁剪功能
ToastUtil.showLongToast(this, getString(R.string.no_crop_action));
@Subscribe
public void finishMeEvent(FinishLocalAlbumActivityEvent event)
myFinish2();
@Override
public void onBackPressed()
myFinish();
private void myFinish()
finish();
if (mRequestType != 2)
overridePendingTransition(0, R.anim.zoomout);
else
overridePendingTransition(0, R.anim.move_out_bottom);
private void myFinish2()
finish();
overridePendingTransition(0, 0);
@Override
protected void onDestroy()
super.onDestroy();
OttoAppConfig.getInstance().unregister(this);
if (null != mBucketLoadTask && mBucketLoadTask.getStatus() == AsyncTask.Status.RUNNING)
mBucketLoadTask.cancel(true);
Helper Methods
/**
* Returns specified directory(/mnt/sdcard/...).
* directory will be created on SD card by defined path if card
* is mounted. Else - Android defines files directory on device's
* files(/data/data/<application package>/files) system.
*
* @param context context
* @param path file path (e.g.: "/AppDir/a.mp3", "/AppDir/files/images/a.jp")
* @return File @link File directory
*/
public static File getFileDirectory(Context context, String path)
File file = null;
if (isHasSDCard())
file = new File(Environment.getExternalStorageDirectory(), path);
if (!file.getParentFile().exists())
if (!file.getParentFile().mkdirs())
file = null;
if (file == null)
// 使用内部缓存[MediaStore.EXTRA_OUTPUT ("output")]是无法正确写入裁切后的图片的。
// 系统是用全局的ContentResolver来做这个过程的文件io操作,app内部的存储被忽略。(猜测)
file = new File(context.getFilesDir(), path);
return file;
/**
* Returns specified directory(/mnt/sdcard/Android/data/<application package>/files/...).
* directory will be created on SD card by defined path if card
* is mounted. Else - Android defines files directory on device's
* files(/data/data/<application package>/files) system.
*
* @param context context
* @param path file path (e.g.: "/music/a.mp3", "/pictures/a.jpg")
* @return File @link File directory
*/
public static File getExternalFileDirectory(Context context, String path)
File file = null;
if (isHasSDCard())
file = new File(context.getExternalFilesDir(null), path);
if (!file.getParentFile().exists())
if (!file.getParentFile().mkdirs())
file = null;
if (file == null)
// 使用内部缓存[MediaStore.EXTRA_OUTPUT ("output")]是无法正确写入裁切后的图片的。
// 系统是用全局的ContentResolver来做这个过程的文件io操作,app内部的存储被忽略。(猜测)
file = new File(context.getFilesDir(), path);
return file;
public static boolean isHasSDCard()
return Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState());
/**
* Returns directory absolutePath.
*
* @param context context
* @param path file path (e.g.: "/AppDir/a.mp3", "/AppDir/files/images/a.jpg")
* @return /mnt/sdcard/Android/data/<application package>/files/....
*/
public static String getFilePath(Context context, String path)
return getExternalFileDirectory(context, path).getAbsolutePath();
/**
* set intent options
*
* @param context context
* @param uri image path uri
* @param filePath save path (e.g.: "/AppDir/a.mp3", "/AppDir/files/images/a.jpg")
* @param type 0,截取壁纸/拍照;1,截取Logo
* @return Intent
*/
public static Intent getCropImageOptions(Context context, Uri uri, String filePath, int type)
int width;
int height;
// 截取壁纸/拍照
if (type == 0)
width = context.getResources().getDisplayMetrics().widthPixels;
height = context.getResources().getDisplayMetrics().heightPixels;
else // 截取logo
width = height = dip2px(context, 30);
//filePath="/Internal storage/Download/a.jpg";
LogUtil.e(LOG_TAG, " filePath:" + filePath );
Intent intent = new Intent();
intent.setAction("com.android.camera.action.CROP");
intent.setDataAndType(uri, "image/*");
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.putExtra("crop", "true");
// 裁剪框比例
intent.putExtra("aspectX", width);
intent.putExtra("aspectY", height);
// 保存路径
//#ToDO: Uri.fromFile change to FileProvider.getUriForFile
Uri mImageUri;
//mImageUri=Uri.fromFile(getExternalFileDirectory(context, filePath));
intent.putExtra(MediaStore.EXTRA_OUTPUT, FileProvider.getUriForFile(context,BuildConfig.APPLICATION_ID+".provider",getExternalFileDirectory(context, filePath)));
// 是否去除面部检测
intent.putExtra("noFaceDetection", true);
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
// 是否保留比例
intent.putExtra("scale", true);
intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
// 裁剪区的宽高
intent.putExtra("outputX", width);
intent.putExtra("outputY", height);
// 是否将数据保留在Bitmap中返回
intent.putExtra("return-data", false);
return intent;
android android-intent android-camera android-manifest
add a comment |
up vote
0
down vote
favorite
I am trying to use camera and save image. Followed the steps as commonsware suggested. Constantly I am getting error -
2018-11-12 02:10:54.588 3145-3173/com.bisw.weac E/DatabaseUtils: Writing exception to parcel
java.lang.SecurityException: Permission Denial: writing android.support.v4.content.FileProvider uri content://com.bisw.weac.provider/external_files/Android/data/com.bisw.weac/files/wallpaper/theme.jpg from pid=5566, uid=10071 requires the provider be exported, or grantUriPermission()
at android.content.ContentProvider.enforceWritePermissionInner(ContentProvider.java:713)
at android.content.ContentProvider$Transport.enforceWritePermission(ContentProvider.java:519)
at android.content.ContentProvider$Transport.enforceFilePermission(ContentProvider.java:491)
at android.content.ContentProvider$Transport.openAssetFile(ContentProvider.java:389)
at android.content.ContentProviderNative.onTransact(ContentProviderNative.java:251)
at android.os.Binder.execTransact(Binder.java:682)
I have tried almost everything like - intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
but nothing helps. I am croping the image from camera.
Activity code
public class LocalAlbumActivity extends BaseActivity implements View.OnClickListener
private static final int REQUEST_IMAGE_CAPTURE_THEME = 1;
private static final int REQUEST_IMAGE_CAPTURE_QRCODE_LOGO = 4;
private static final int REQUEST_IMAGE_CROP_THEME = 2;
private static final int REQUEST_IMAGE_CROP_QRCODE_LOGO = 5;
private static final int REQUEST_ALBUM_DETAIL = 3;
public static final String ALBUM_PATH = "album_path";
public static final String ALBUM_NAME = "album_name";
private LocalAlbumAdapter mLocalAlbumAdapter;
private List<ImageBucket> mLocalAlbumList;
private AsyncTask<Void, Void, List<ImageBucket>> mBucketLoadTask;
private ListView mLocalAlbumListView;
/**
* 访问本地相册类型:0,主题;1,扫码;2,造码
*/
private int mRequestType;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
OttoAppConfig.getInstance().register(this);
setContentView(R.layout.activity_local_album);
ViewGroup backGround = (ViewGroup) findViewById(R.id.background);
MyUtil.setBackgroundBlur(backGround, this);
initAdapter();
assignViews();
private void initAdapter()
mLocalAlbumList = new ArrayList<>();
mLocalAlbumAdapter = new LocalAlbumAdapter(this, mLocalAlbumList);
//trying permission
mBucketLoadTask = new AsyncTask<Void, Void, List<ImageBucket>>()
@Override
protected void onPreExecute()
super.onPreExecute();
// showLoading();
@Override
protected List<ImageBucket> doInBackground(Void... params)
return LocalAlbumImagePickerHelper.getInstance(LocalAlbumActivity.this)
.getImagesBucketList();
@Override
protected void onPostExecute(List<ImageBucket> list)
dismissLoadingDialog();
TextView emptyView = (TextView) findViewById(R.id.local_album_lv_empty);
mLocalAlbumListView.setEmptyView(emptyView);
mLocalAlbumList.addAll(list);
mLocalAlbumAdapter.notifyDataSetChanged();
;
mBucketLoadTask.execute();
private void dismissLoadingDialog()
ViewGroup progressBarLlyt = (ViewGroup) findViewById(R.id.progress_bar_llyt);
progressBarLlyt.setVisibility(View.GONE);
private void assignViews()
TextView loadingMsg = (TextView) findViewById(R.id.loading_msg);
loadingMsg.setText(R.string.scanning);
ImageView backBtn = (ImageView) findViewById(R.id.action_back);
TextView captureBtn = (TextView) findViewById(R.id.action_capture);
backBtn.setOnClickListener(this);
mRequestType = getIntent().getIntExtra(WeacConstants.REQUEST_LOCAL_ALBUM_TYPE, 0);
switch (mRequestType)
// 主题
case 0:
// 造码
case 2:
captureBtn.setOnClickListener(this);
break;
// 扫码
case 1:
// 隐藏拍照按钮
captureBtn.setVisibility(View.GONE);
break;
mLocalAlbumListView = (ListView) findViewById(R.id.local_album_lv);
mLocalAlbumListView.setAdapter(mLocalAlbumAdapter);
mLocalAlbumListView.setOnItemClickListener(new AdapterView.OnItemClickListener()
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
if (MyUtil.isFastDoubleClick())
return;
Intent intent = new Intent(LocalAlbumActivity.this, LocalAlbumDetailActivity.class);
intent.putParcelableArrayListExtra(ALBUM_PATH,
mLocalAlbumAdapter.getItem(position).bucketList);
intent.putExtra(ALBUM_NAME, mLocalAlbumAdapter.getItem(position).bucketName);
intent.putExtra(WeacConstants.REQUEST_LOCAL_ALBUM_TYPE, mRequestType);
startActivityForResult(intent, REQUEST_ALBUM_DETAIL);
);
// OverScrollDecoratorHelper.setUpOverScroll(mLocalAlbumListView);
private Uri mImageUri;
@Override
public void onClick(View v)
switch (v.getId())
// 返回
case R.id.action_back:
myFinish();
break;
// 拍照
case R.id.action_capture:
PackageManager pm = getPackageManager();
// FEATURE_CAMERA - 后置相机
// FEATURE_CAMERA_FRONT - 前置相机
if (pm.hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY)) Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.putExtra(MediaStore.EXTRA_OUTPUT, mImageUri);
startActivityForResult(intent, requestType);
overridePendingTransition(0, R.anim.zoomin);
else // 没有可用相机
Intent intent = new Intent(this, MyDialogActivitySingle.class);
intent.putExtra(WeacConstants.TITLE, getString(R.string.prompt));
intent.putExtra(WeacConstants.DETAIL, getString(R.string.camera_error));
startActivity(intent);
break;
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
super.onActivityResult(requestCode, resultCode, data);
if (resultCode != RESULT_OK)
// 截图/相机返回
overridePendingTransition(0, R.anim.zoomout);
return;
// 扫描二维码相册详细取消
if (data != null)
boolean isFinishMe = data.getBooleanExtra(LocalAlbumDetailActivity.FINISH_ACTIVITY, false);
if (isFinishMe && !isFinishing())
myFinish2();
return;
switch (requestCode)
// 拍照(截取主题壁纸)
case REQUEST_IMAGE_CAPTURE_THEME:
cropImage(0, REQUEST_IMAGE_CROP_THEME, WeacConstants.DIY_WALLPAPER_PATH);
break;
// 拍照(截取二维码logo)
case REQUEST_IMAGE_CAPTURE_QRCODE_LOGO:
cropImage(1, REQUEST_IMAGE_CROP_QRCODE_LOGO, WeacConstants.DIY_QRCODE_LOGO_PATH);
break;
// 截图(截取主题壁纸)
case REQUEST_IMAGE_CROP_THEME:
String filePath = MyUtil.getFilePath(this, WeacConstants.DIY_WALLPAPER_PATH);
// 更新壁纸信息
MyUtil.saveWallpaper(this, WeacConstants.WALLPAPER_PATH, filePath);
// 发送壁纸更新事件
OttoAppConfig.getInstance().post(new WallpaperEvent());
myFinish();
break;
// 截图(截取二维码logo)
case REQUEST_IMAGE_CROP_QRCODE_LOGO:
String logoPath = MyUtil.getFilePath(this, WeacConstants.DIY_QRCODE_LOGO_PATH);
// 保存自定义二维码logo地址
MyUtil.saveQRcodeLogoPath(this, logoPath);
// 发送自定义二维码logo截取地址事件
OttoAppConfig.getInstance().post(new QRcodeLogoEvent(logoPath));
myFinish();
break;
// 相册详细图片
case REQUEST_ALBUM_DETAIL:
assert data != null;
String url = data.getStringExtra(WeacConstants.IMAGE_URL);
OttoAppConfig.getInstance().post(new ScanCodeEvent(url));
myFinish2();
break;
private void cropImage(int type, int requestType, String path)
ToastUtil.showLongToast(this, "path:"+path);
Intent intent = MyUtil.getCropImageOptions(this, mImageUri, path, type);
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
if (intent.resolveActivity(getPackageManager()) != null)
startActivityForResult(intent, requestType);
overridePendingTransition(0, 0);
else
// 不可以复制其他应用的内部文件
// TODO: 全屏裁剪&自定义裁剪功能
ToastUtil.showLongToast(this, getString(R.string.no_crop_action));
@Subscribe
public void finishMeEvent(FinishLocalAlbumActivityEvent event)
myFinish2();
@Override
public void onBackPressed()
myFinish();
private void myFinish()
finish();
if (mRequestType != 2)
overridePendingTransition(0, R.anim.zoomout);
else
overridePendingTransition(0, R.anim.move_out_bottom);
private void myFinish2()
finish();
overridePendingTransition(0, 0);
@Override
protected void onDestroy()
super.onDestroy();
OttoAppConfig.getInstance().unregister(this);
if (null != mBucketLoadTask && mBucketLoadTask.getStatus() == AsyncTask.Status.RUNNING)
mBucketLoadTask.cancel(true);
Helper Methods
/**
* Returns specified directory(/mnt/sdcard/...).
* directory will be created on SD card by defined path if card
* is mounted. Else - Android defines files directory on device's
* files(/data/data/<application package>/files) system.
*
* @param context context
* @param path file path (e.g.: "/AppDir/a.mp3", "/AppDir/files/images/a.jp")
* @return File @link File directory
*/
public static File getFileDirectory(Context context, String path)
File file = null;
if (isHasSDCard())
file = new File(Environment.getExternalStorageDirectory(), path);
if (!file.getParentFile().exists())
if (!file.getParentFile().mkdirs())
file = null;
if (file == null)
// 使用内部缓存[MediaStore.EXTRA_OUTPUT ("output")]是无法正确写入裁切后的图片的。
// 系统是用全局的ContentResolver来做这个过程的文件io操作,app内部的存储被忽略。(猜测)
file = new File(context.getFilesDir(), path);
return file;
/**
* Returns specified directory(/mnt/sdcard/Android/data/<application package>/files/...).
* directory will be created on SD card by defined path if card
* is mounted. Else - Android defines files directory on device's
* files(/data/data/<application package>/files) system.
*
* @param context context
* @param path file path (e.g.: "/music/a.mp3", "/pictures/a.jpg")
* @return File @link File directory
*/
public static File getExternalFileDirectory(Context context, String path)
File file = null;
if (isHasSDCard())
file = new File(context.getExternalFilesDir(null), path);
if (!file.getParentFile().exists())
if (!file.getParentFile().mkdirs())
file = null;
if (file == null)
// 使用内部缓存[MediaStore.EXTRA_OUTPUT ("output")]是无法正确写入裁切后的图片的。
// 系统是用全局的ContentResolver来做这个过程的文件io操作,app内部的存储被忽略。(猜测)
file = new File(context.getFilesDir(), path);
return file;
public static boolean isHasSDCard()
return Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState());
/**
* Returns directory absolutePath.
*
* @param context context
* @param path file path (e.g.: "/AppDir/a.mp3", "/AppDir/files/images/a.jpg")
* @return /mnt/sdcard/Android/data/<application package>/files/....
*/
public static String getFilePath(Context context, String path)
return getExternalFileDirectory(context, path).getAbsolutePath();
/**
* set intent options
*
* @param context context
* @param uri image path uri
* @param filePath save path (e.g.: "/AppDir/a.mp3", "/AppDir/files/images/a.jpg")
* @param type 0,截取壁纸/拍照;1,截取Logo
* @return Intent
*/
public static Intent getCropImageOptions(Context context, Uri uri, String filePath, int type)
int width;
int height;
// 截取壁纸/拍照
if (type == 0)
width = context.getResources().getDisplayMetrics().widthPixels;
height = context.getResources().getDisplayMetrics().heightPixels;
else // 截取logo
width = height = dip2px(context, 30);
//filePath="/Internal storage/Download/a.jpg";
LogUtil.e(LOG_TAG, " filePath:" + filePath );
Intent intent = new Intent();
intent.setAction("com.android.camera.action.CROP");
intent.setDataAndType(uri, "image/*");
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.putExtra("crop", "true");
// 裁剪框比例
intent.putExtra("aspectX", width);
intent.putExtra("aspectY", height);
// 保存路径
//#ToDO: Uri.fromFile change to FileProvider.getUriForFile
Uri mImageUri;
//mImageUri=Uri.fromFile(getExternalFileDirectory(context, filePath));
intent.putExtra(MediaStore.EXTRA_OUTPUT, FileProvider.getUriForFile(context,BuildConfig.APPLICATION_ID+".provider",getExternalFileDirectory(context, filePath)));
// 是否去除面部检测
intent.putExtra("noFaceDetection", true);
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
// 是否保留比例
intent.putExtra("scale", true);
intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
// 裁剪区的宽高
intent.putExtra("outputX", width);
intent.putExtra("outputY", height);
// 是否将数据保留在Bitmap中返回
intent.putExtra("return-data", false);
return intent;
android android-intent android-camera android-manifest
add a comment |
up vote
0
down vote
favorite
up vote
0
down vote
favorite
I am trying to use camera and save image. Followed the steps as commonsware suggested. Constantly I am getting error -
2018-11-12 02:10:54.588 3145-3173/com.bisw.weac E/DatabaseUtils: Writing exception to parcel
java.lang.SecurityException: Permission Denial: writing android.support.v4.content.FileProvider uri content://com.bisw.weac.provider/external_files/Android/data/com.bisw.weac/files/wallpaper/theme.jpg from pid=5566, uid=10071 requires the provider be exported, or grantUriPermission()
at android.content.ContentProvider.enforceWritePermissionInner(ContentProvider.java:713)
at android.content.ContentProvider$Transport.enforceWritePermission(ContentProvider.java:519)
at android.content.ContentProvider$Transport.enforceFilePermission(ContentProvider.java:491)
at android.content.ContentProvider$Transport.openAssetFile(ContentProvider.java:389)
at android.content.ContentProviderNative.onTransact(ContentProviderNative.java:251)
at android.os.Binder.execTransact(Binder.java:682)
I have tried almost everything like - intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
but nothing helps. I am croping the image from camera.
Activity code
public class LocalAlbumActivity extends BaseActivity implements View.OnClickListener
private static final int REQUEST_IMAGE_CAPTURE_THEME = 1;
private static final int REQUEST_IMAGE_CAPTURE_QRCODE_LOGO = 4;
private static final int REQUEST_IMAGE_CROP_THEME = 2;
private static final int REQUEST_IMAGE_CROP_QRCODE_LOGO = 5;
private static final int REQUEST_ALBUM_DETAIL = 3;
public static final String ALBUM_PATH = "album_path";
public static final String ALBUM_NAME = "album_name";
private LocalAlbumAdapter mLocalAlbumAdapter;
private List<ImageBucket> mLocalAlbumList;
private AsyncTask<Void, Void, List<ImageBucket>> mBucketLoadTask;
private ListView mLocalAlbumListView;
/**
* 访问本地相册类型:0,主题;1,扫码;2,造码
*/
private int mRequestType;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
OttoAppConfig.getInstance().register(this);
setContentView(R.layout.activity_local_album);
ViewGroup backGround = (ViewGroup) findViewById(R.id.background);
MyUtil.setBackgroundBlur(backGround, this);
initAdapter();
assignViews();
private void initAdapter()
mLocalAlbumList = new ArrayList<>();
mLocalAlbumAdapter = new LocalAlbumAdapter(this, mLocalAlbumList);
//trying permission
mBucketLoadTask = new AsyncTask<Void, Void, List<ImageBucket>>()
@Override
protected void onPreExecute()
super.onPreExecute();
// showLoading();
@Override
protected List<ImageBucket> doInBackground(Void... params)
return LocalAlbumImagePickerHelper.getInstance(LocalAlbumActivity.this)
.getImagesBucketList();
@Override
protected void onPostExecute(List<ImageBucket> list)
dismissLoadingDialog();
TextView emptyView = (TextView) findViewById(R.id.local_album_lv_empty);
mLocalAlbumListView.setEmptyView(emptyView);
mLocalAlbumList.addAll(list);
mLocalAlbumAdapter.notifyDataSetChanged();
;
mBucketLoadTask.execute();
private void dismissLoadingDialog()
ViewGroup progressBarLlyt = (ViewGroup) findViewById(R.id.progress_bar_llyt);
progressBarLlyt.setVisibility(View.GONE);
private void assignViews()
TextView loadingMsg = (TextView) findViewById(R.id.loading_msg);
loadingMsg.setText(R.string.scanning);
ImageView backBtn = (ImageView) findViewById(R.id.action_back);
TextView captureBtn = (TextView) findViewById(R.id.action_capture);
backBtn.setOnClickListener(this);
mRequestType = getIntent().getIntExtra(WeacConstants.REQUEST_LOCAL_ALBUM_TYPE, 0);
switch (mRequestType)
// 主题
case 0:
// 造码
case 2:
captureBtn.setOnClickListener(this);
break;
// 扫码
case 1:
// 隐藏拍照按钮
captureBtn.setVisibility(View.GONE);
break;
mLocalAlbumListView = (ListView) findViewById(R.id.local_album_lv);
mLocalAlbumListView.setAdapter(mLocalAlbumAdapter);
mLocalAlbumListView.setOnItemClickListener(new AdapterView.OnItemClickListener()
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
if (MyUtil.isFastDoubleClick())
return;
Intent intent = new Intent(LocalAlbumActivity.this, LocalAlbumDetailActivity.class);
intent.putParcelableArrayListExtra(ALBUM_PATH,
mLocalAlbumAdapter.getItem(position).bucketList);
intent.putExtra(ALBUM_NAME, mLocalAlbumAdapter.getItem(position).bucketName);
intent.putExtra(WeacConstants.REQUEST_LOCAL_ALBUM_TYPE, mRequestType);
startActivityForResult(intent, REQUEST_ALBUM_DETAIL);
);
// OverScrollDecoratorHelper.setUpOverScroll(mLocalAlbumListView);
private Uri mImageUri;
@Override
public void onClick(View v)
switch (v.getId())
// 返回
case R.id.action_back:
myFinish();
break;
// 拍照
case R.id.action_capture:
PackageManager pm = getPackageManager();
// FEATURE_CAMERA - 后置相机
// FEATURE_CAMERA_FRONT - 前置相机
if (pm.hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY)) Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.putExtra(MediaStore.EXTRA_OUTPUT, mImageUri);
startActivityForResult(intent, requestType);
overridePendingTransition(0, R.anim.zoomin);
else // 没有可用相机
Intent intent = new Intent(this, MyDialogActivitySingle.class);
intent.putExtra(WeacConstants.TITLE, getString(R.string.prompt));
intent.putExtra(WeacConstants.DETAIL, getString(R.string.camera_error));
startActivity(intent);
break;
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
super.onActivityResult(requestCode, resultCode, data);
if (resultCode != RESULT_OK)
// 截图/相机返回
overridePendingTransition(0, R.anim.zoomout);
return;
// 扫描二维码相册详细取消
if (data != null)
boolean isFinishMe = data.getBooleanExtra(LocalAlbumDetailActivity.FINISH_ACTIVITY, false);
if (isFinishMe && !isFinishing())
myFinish2();
return;
switch (requestCode)
// 拍照(截取主题壁纸)
case REQUEST_IMAGE_CAPTURE_THEME:
cropImage(0, REQUEST_IMAGE_CROP_THEME, WeacConstants.DIY_WALLPAPER_PATH);
break;
// 拍照(截取二维码logo)
case REQUEST_IMAGE_CAPTURE_QRCODE_LOGO:
cropImage(1, REQUEST_IMAGE_CROP_QRCODE_LOGO, WeacConstants.DIY_QRCODE_LOGO_PATH);
break;
// 截图(截取主题壁纸)
case REQUEST_IMAGE_CROP_THEME:
String filePath = MyUtil.getFilePath(this, WeacConstants.DIY_WALLPAPER_PATH);
// 更新壁纸信息
MyUtil.saveWallpaper(this, WeacConstants.WALLPAPER_PATH, filePath);
// 发送壁纸更新事件
OttoAppConfig.getInstance().post(new WallpaperEvent());
myFinish();
break;
// 截图(截取二维码logo)
case REQUEST_IMAGE_CROP_QRCODE_LOGO:
String logoPath = MyUtil.getFilePath(this, WeacConstants.DIY_QRCODE_LOGO_PATH);
// 保存自定义二维码logo地址
MyUtil.saveQRcodeLogoPath(this, logoPath);
// 发送自定义二维码logo截取地址事件
OttoAppConfig.getInstance().post(new QRcodeLogoEvent(logoPath));
myFinish();
break;
// 相册详细图片
case REQUEST_ALBUM_DETAIL:
assert data != null;
String url = data.getStringExtra(WeacConstants.IMAGE_URL);
OttoAppConfig.getInstance().post(new ScanCodeEvent(url));
myFinish2();
break;
private void cropImage(int type, int requestType, String path)
ToastUtil.showLongToast(this, "path:"+path);
Intent intent = MyUtil.getCropImageOptions(this, mImageUri, path, type);
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
if (intent.resolveActivity(getPackageManager()) != null)
startActivityForResult(intent, requestType);
overridePendingTransition(0, 0);
else
// 不可以复制其他应用的内部文件
// TODO: 全屏裁剪&自定义裁剪功能
ToastUtil.showLongToast(this, getString(R.string.no_crop_action));
@Subscribe
public void finishMeEvent(FinishLocalAlbumActivityEvent event)
myFinish2();
@Override
public void onBackPressed()
myFinish();
private void myFinish()
finish();
if (mRequestType != 2)
overridePendingTransition(0, R.anim.zoomout);
else
overridePendingTransition(0, R.anim.move_out_bottom);
private void myFinish2()
finish();
overridePendingTransition(0, 0);
@Override
protected void onDestroy()
super.onDestroy();
OttoAppConfig.getInstance().unregister(this);
if (null != mBucketLoadTask && mBucketLoadTask.getStatus() == AsyncTask.Status.RUNNING)
mBucketLoadTask.cancel(true);
Helper Methods
/**
* Returns specified directory(/mnt/sdcard/...).
* directory will be created on SD card by defined path if card
* is mounted. Else - Android defines files directory on device's
* files(/data/data/<application package>/files) system.
*
* @param context context
* @param path file path (e.g.: "/AppDir/a.mp3", "/AppDir/files/images/a.jp")
* @return File @link File directory
*/
public static File getFileDirectory(Context context, String path)
File file = null;
if (isHasSDCard())
file = new File(Environment.getExternalStorageDirectory(), path);
if (!file.getParentFile().exists())
if (!file.getParentFile().mkdirs())
file = null;
if (file == null)
// 使用内部缓存[MediaStore.EXTRA_OUTPUT ("output")]是无法正确写入裁切后的图片的。
// 系统是用全局的ContentResolver来做这个过程的文件io操作,app内部的存储被忽略。(猜测)
file = new File(context.getFilesDir(), path);
return file;
/**
* Returns specified directory(/mnt/sdcard/Android/data/<application package>/files/...).
* directory will be created on SD card by defined path if card
* is mounted. Else - Android defines files directory on device's
* files(/data/data/<application package>/files) system.
*
* @param context context
* @param path file path (e.g.: "/music/a.mp3", "/pictures/a.jpg")
* @return File @link File directory
*/
public static File getExternalFileDirectory(Context context, String path)
File file = null;
if (isHasSDCard())
file = new File(context.getExternalFilesDir(null), path);
if (!file.getParentFile().exists())
if (!file.getParentFile().mkdirs())
file = null;
if (file == null)
// 使用内部缓存[MediaStore.EXTRA_OUTPUT ("output")]是无法正确写入裁切后的图片的。
// 系统是用全局的ContentResolver来做这个过程的文件io操作,app内部的存储被忽略。(猜测)
file = new File(context.getFilesDir(), path);
return file;
public static boolean isHasSDCard()
return Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState());
/**
* Returns directory absolutePath.
*
* @param context context
* @param path file path (e.g.: "/AppDir/a.mp3", "/AppDir/files/images/a.jpg")
* @return /mnt/sdcard/Android/data/<application package>/files/....
*/
public static String getFilePath(Context context, String path)
return getExternalFileDirectory(context, path).getAbsolutePath();
/**
* set intent options
*
* @param context context
* @param uri image path uri
* @param filePath save path (e.g.: "/AppDir/a.mp3", "/AppDir/files/images/a.jpg")
* @param type 0,截取壁纸/拍照;1,截取Logo
* @return Intent
*/
public static Intent getCropImageOptions(Context context, Uri uri, String filePath, int type)
int width;
int height;
// 截取壁纸/拍照
if (type == 0)
width = context.getResources().getDisplayMetrics().widthPixels;
height = context.getResources().getDisplayMetrics().heightPixels;
else // 截取logo
width = height = dip2px(context, 30);
//filePath="/Internal storage/Download/a.jpg";
LogUtil.e(LOG_TAG, " filePath:" + filePath );
Intent intent = new Intent();
intent.setAction("com.android.camera.action.CROP");
intent.setDataAndType(uri, "image/*");
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.putExtra("crop", "true");
// 裁剪框比例
intent.putExtra("aspectX", width);
intent.putExtra("aspectY", height);
// 保存路径
//#ToDO: Uri.fromFile change to FileProvider.getUriForFile
Uri mImageUri;
//mImageUri=Uri.fromFile(getExternalFileDirectory(context, filePath));
intent.putExtra(MediaStore.EXTRA_OUTPUT, FileProvider.getUriForFile(context,BuildConfig.APPLICATION_ID+".provider",getExternalFileDirectory(context, filePath)));
// 是否去除面部检测
intent.putExtra("noFaceDetection", true);
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
// 是否保留比例
intent.putExtra("scale", true);
intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
// 裁剪区的宽高
intent.putExtra("outputX", width);
intent.putExtra("outputY", height);
// 是否将数据保留在Bitmap中返回
intent.putExtra("return-data", false);
return intent;
android android-intent android-camera android-manifest
I am trying to use camera and save image. Followed the steps as commonsware suggested. Constantly I am getting error -
2018-11-12 02:10:54.588 3145-3173/com.bisw.weac E/DatabaseUtils: Writing exception to parcel
java.lang.SecurityException: Permission Denial: writing android.support.v4.content.FileProvider uri content://com.bisw.weac.provider/external_files/Android/data/com.bisw.weac/files/wallpaper/theme.jpg from pid=5566, uid=10071 requires the provider be exported, or grantUriPermission()
at android.content.ContentProvider.enforceWritePermissionInner(ContentProvider.java:713)
at android.content.ContentProvider$Transport.enforceWritePermission(ContentProvider.java:519)
at android.content.ContentProvider$Transport.enforceFilePermission(ContentProvider.java:491)
at android.content.ContentProvider$Transport.openAssetFile(ContentProvider.java:389)
at android.content.ContentProviderNative.onTransact(ContentProviderNative.java:251)
at android.os.Binder.execTransact(Binder.java:682)
I have tried almost everything like - intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
but nothing helps. I am croping the image from camera.
Activity code
public class LocalAlbumActivity extends BaseActivity implements View.OnClickListener
private static final int REQUEST_IMAGE_CAPTURE_THEME = 1;
private static final int REQUEST_IMAGE_CAPTURE_QRCODE_LOGO = 4;
private static final int REQUEST_IMAGE_CROP_THEME = 2;
private static final int REQUEST_IMAGE_CROP_QRCODE_LOGO = 5;
private static final int REQUEST_ALBUM_DETAIL = 3;
public static final String ALBUM_PATH = "album_path";
public static final String ALBUM_NAME = "album_name";
private LocalAlbumAdapter mLocalAlbumAdapter;
private List<ImageBucket> mLocalAlbumList;
private AsyncTask<Void, Void, List<ImageBucket>> mBucketLoadTask;
private ListView mLocalAlbumListView;
/**
* 访问本地相册类型:0,主题;1,扫码;2,造码
*/
private int mRequestType;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
OttoAppConfig.getInstance().register(this);
setContentView(R.layout.activity_local_album);
ViewGroup backGround = (ViewGroup) findViewById(R.id.background);
MyUtil.setBackgroundBlur(backGround, this);
initAdapter();
assignViews();
private void initAdapter()
mLocalAlbumList = new ArrayList<>();
mLocalAlbumAdapter = new LocalAlbumAdapter(this, mLocalAlbumList);
//trying permission
mBucketLoadTask = new AsyncTask<Void, Void, List<ImageBucket>>()
@Override
protected void onPreExecute()
super.onPreExecute();
// showLoading();
@Override
protected List<ImageBucket> doInBackground(Void... params)
return LocalAlbumImagePickerHelper.getInstance(LocalAlbumActivity.this)
.getImagesBucketList();
@Override
protected void onPostExecute(List<ImageBucket> list)
dismissLoadingDialog();
TextView emptyView = (TextView) findViewById(R.id.local_album_lv_empty);
mLocalAlbumListView.setEmptyView(emptyView);
mLocalAlbumList.addAll(list);
mLocalAlbumAdapter.notifyDataSetChanged();
;
mBucketLoadTask.execute();
private void dismissLoadingDialog()
ViewGroup progressBarLlyt = (ViewGroup) findViewById(R.id.progress_bar_llyt);
progressBarLlyt.setVisibility(View.GONE);
private void assignViews()
TextView loadingMsg = (TextView) findViewById(R.id.loading_msg);
loadingMsg.setText(R.string.scanning);
ImageView backBtn = (ImageView) findViewById(R.id.action_back);
TextView captureBtn = (TextView) findViewById(R.id.action_capture);
backBtn.setOnClickListener(this);
mRequestType = getIntent().getIntExtra(WeacConstants.REQUEST_LOCAL_ALBUM_TYPE, 0);
switch (mRequestType)
// 主题
case 0:
// 造码
case 2:
captureBtn.setOnClickListener(this);
break;
// 扫码
case 1:
// 隐藏拍照按钮
captureBtn.setVisibility(View.GONE);
break;
mLocalAlbumListView = (ListView) findViewById(R.id.local_album_lv);
mLocalAlbumListView.setAdapter(mLocalAlbumAdapter);
mLocalAlbumListView.setOnItemClickListener(new AdapterView.OnItemClickListener()
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
if (MyUtil.isFastDoubleClick())
return;
Intent intent = new Intent(LocalAlbumActivity.this, LocalAlbumDetailActivity.class);
intent.putParcelableArrayListExtra(ALBUM_PATH,
mLocalAlbumAdapter.getItem(position).bucketList);
intent.putExtra(ALBUM_NAME, mLocalAlbumAdapter.getItem(position).bucketName);
intent.putExtra(WeacConstants.REQUEST_LOCAL_ALBUM_TYPE, mRequestType);
startActivityForResult(intent, REQUEST_ALBUM_DETAIL);
);
// OverScrollDecoratorHelper.setUpOverScroll(mLocalAlbumListView);
private Uri mImageUri;
@Override
public void onClick(View v)
switch (v.getId())
// 返回
case R.id.action_back:
myFinish();
break;
// 拍照
case R.id.action_capture:
PackageManager pm = getPackageManager();
// FEATURE_CAMERA - 后置相机
// FEATURE_CAMERA_FRONT - 前置相机
if (pm.hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY)) Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.putExtra(MediaStore.EXTRA_OUTPUT, mImageUri);
startActivityForResult(intent, requestType);
overridePendingTransition(0, R.anim.zoomin);
else // 没有可用相机
Intent intent = new Intent(this, MyDialogActivitySingle.class);
intent.putExtra(WeacConstants.TITLE, getString(R.string.prompt));
intent.putExtra(WeacConstants.DETAIL, getString(R.string.camera_error));
startActivity(intent);
break;
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
super.onActivityResult(requestCode, resultCode, data);
if (resultCode != RESULT_OK)
// 截图/相机返回
overridePendingTransition(0, R.anim.zoomout);
return;
// 扫描二维码相册详细取消
if (data != null)
boolean isFinishMe = data.getBooleanExtra(LocalAlbumDetailActivity.FINISH_ACTIVITY, false);
if (isFinishMe && !isFinishing())
myFinish2();
return;
switch (requestCode)
// 拍照(截取主题壁纸)
case REQUEST_IMAGE_CAPTURE_THEME:
cropImage(0, REQUEST_IMAGE_CROP_THEME, WeacConstants.DIY_WALLPAPER_PATH);
break;
// 拍照(截取二维码logo)
case REQUEST_IMAGE_CAPTURE_QRCODE_LOGO:
cropImage(1, REQUEST_IMAGE_CROP_QRCODE_LOGO, WeacConstants.DIY_QRCODE_LOGO_PATH);
break;
// 截图(截取主题壁纸)
case REQUEST_IMAGE_CROP_THEME:
String filePath = MyUtil.getFilePath(this, WeacConstants.DIY_WALLPAPER_PATH);
// 更新壁纸信息
MyUtil.saveWallpaper(this, WeacConstants.WALLPAPER_PATH, filePath);
// 发送壁纸更新事件
OttoAppConfig.getInstance().post(new WallpaperEvent());
myFinish();
break;
// 截图(截取二维码logo)
case REQUEST_IMAGE_CROP_QRCODE_LOGO:
String logoPath = MyUtil.getFilePath(this, WeacConstants.DIY_QRCODE_LOGO_PATH);
// 保存自定义二维码logo地址
MyUtil.saveQRcodeLogoPath(this, logoPath);
// 发送自定义二维码logo截取地址事件
OttoAppConfig.getInstance().post(new QRcodeLogoEvent(logoPath));
myFinish();
break;
// 相册详细图片
case REQUEST_ALBUM_DETAIL:
assert data != null;
String url = data.getStringExtra(WeacConstants.IMAGE_URL);
OttoAppConfig.getInstance().post(new ScanCodeEvent(url));
myFinish2();
break;
private void cropImage(int type, int requestType, String path)
ToastUtil.showLongToast(this, "path:"+path);
Intent intent = MyUtil.getCropImageOptions(this, mImageUri, path, type);
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
if (intent.resolveActivity(getPackageManager()) != null)
startActivityForResult(intent, requestType);
overridePendingTransition(0, 0);
else
// 不可以复制其他应用的内部文件
// TODO: 全屏裁剪&自定义裁剪功能
ToastUtil.showLongToast(this, getString(R.string.no_crop_action));
@Subscribe
public void finishMeEvent(FinishLocalAlbumActivityEvent event)
myFinish2();
@Override
public void onBackPressed()
myFinish();
private void myFinish()
finish();
if (mRequestType != 2)
overridePendingTransition(0, R.anim.zoomout);
else
overridePendingTransition(0, R.anim.move_out_bottom);
private void myFinish2()
finish();
overridePendingTransition(0, 0);
@Override
protected void onDestroy()
super.onDestroy();
OttoAppConfig.getInstance().unregister(this);
if (null != mBucketLoadTask && mBucketLoadTask.getStatus() == AsyncTask.Status.RUNNING)
mBucketLoadTask.cancel(true);
Helper Methods
/**
* Returns specified directory(/mnt/sdcard/...).
* directory will be created on SD card by defined path if card
* is mounted. Else - Android defines files directory on device's
* files(/data/data/<application package>/files) system.
*
* @param context context
* @param path file path (e.g.: "/AppDir/a.mp3", "/AppDir/files/images/a.jp")
* @return File @link File directory
*/
public static File getFileDirectory(Context context, String path)
File file = null;
if (isHasSDCard())
file = new File(Environment.getExternalStorageDirectory(), path);
if (!file.getParentFile().exists())
if (!file.getParentFile().mkdirs())
file = null;
if (file == null)
// 使用内部缓存[MediaStore.EXTRA_OUTPUT ("output")]是无法正确写入裁切后的图片的。
// 系统是用全局的ContentResolver来做这个过程的文件io操作,app内部的存储被忽略。(猜测)
file = new File(context.getFilesDir(), path);
return file;
/**
* Returns specified directory(/mnt/sdcard/Android/data/<application package>/files/...).
* directory will be created on SD card by defined path if card
* is mounted. Else - Android defines files directory on device's
* files(/data/data/<application package>/files) system.
*
* @param context context
* @param path file path (e.g.: "/music/a.mp3", "/pictures/a.jpg")
* @return File @link File directory
*/
public static File getExternalFileDirectory(Context context, String path)
File file = null;
if (isHasSDCard())
file = new File(context.getExternalFilesDir(null), path);
if (!file.getParentFile().exists())
if (!file.getParentFile().mkdirs())
file = null;
if (file == null)
// 使用内部缓存[MediaStore.EXTRA_OUTPUT ("output")]是无法正确写入裁切后的图片的。
// 系统是用全局的ContentResolver来做这个过程的文件io操作,app内部的存储被忽略。(猜测)
file = new File(context.getFilesDir(), path);
return file;
public static boolean isHasSDCard()
return Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState());
/**
* Returns directory absolutePath.
*
* @param context context
* @param path file path (e.g.: "/AppDir/a.mp3", "/AppDir/files/images/a.jpg")
* @return /mnt/sdcard/Android/data/<application package>/files/....
*/
public static String getFilePath(Context context, String path)
return getExternalFileDirectory(context, path).getAbsolutePath();
/**
* set intent options
*
* @param context context
* @param uri image path uri
* @param filePath save path (e.g.: "/AppDir/a.mp3", "/AppDir/files/images/a.jpg")
* @param type 0,截取壁纸/拍照;1,截取Logo
* @return Intent
*/
public static Intent getCropImageOptions(Context context, Uri uri, String filePath, int type)
int width;
int height;
// 截取壁纸/拍照
if (type == 0)
width = context.getResources().getDisplayMetrics().widthPixels;
height = context.getResources().getDisplayMetrics().heightPixels;
else // 截取logo
width = height = dip2px(context, 30);
//filePath="/Internal storage/Download/a.jpg";
LogUtil.e(LOG_TAG, " filePath:" + filePath );
Intent intent = new Intent();
intent.setAction("com.android.camera.action.CROP");
intent.setDataAndType(uri, "image/*");
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.putExtra("crop", "true");
// 裁剪框比例
intent.putExtra("aspectX", width);
intent.putExtra("aspectY", height);
// 保存路径
//#ToDO: Uri.fromFile change to FileProvider.getUriForFile
Uri mImageUri;
//mImageUri=Uri.fromFile(getExternalFileDirectory(context, filePath));
intent.putExtra(MediaStore.EXTRA_OUTPUT, FileProvider.getUriForFile(context,BuildConfig.APPLICATION_ID+".provider",getExternalFileDirectory(context, filePath)));
// 是否去除面部检测
intent.putExtra("noFaceDetection", true);
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
// 是否保留比例
intent.putExtra("scale", true);
intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
// 裁剪区的宽高
intent.putExtra("outputX", width);
intent.putExtra("outputY", height);
// 是否将数据保留在Bitmap中返回
intent.putExtra("return-data", false);
return intent;
android android-intent android-camera android-manifest
android android-intent android-camera android-manifest
asked Nov 12 at 2:31
Biswajit Das
317418
317418
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
up vote
0
down vote
You need to add the following in provider declaration in your manifest file
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="<application-id>.fileprovider" // com.abc.def
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths" />
</provider>
I have already done the same as described link. One differance isandroid:authorities="<application-id>.fileprovider"
withandroid:authorities="$applicationId.my.package.name.provider"
Does it make any difference?
– Biswajit Das
Nov 12 at 16:52
You use this $applicationId.my.package.name.provider if you have a custom FileProvider class extending Android FileProvider class. If you dont have one then you need to use $applicationId.fileprovider
– Vishal Arora
Nov 13 at 5:59
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53255297%2fjava-lang-securityexception-permission-denial-writing-android-support-v4-conte%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
0
down vote
You need to add the following in provider declaration in your manifest file
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="<application-id>.fileprovider" // com.abc.def
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths" />
</provider>
I have already done the same as described link. One differance isandroid:authorities="<application-id>.fileprovider"
withandroid:authorities="$applicationId.my.package.name.provider"
Does it make any difference?
– Biswajit Das
Nov 12 at 16:52
You use this $applicationId.my.package.name.provider if you have a custom FileProvider class extending Android FileProvider class. If you dont have one then you need to use $applicationId.fileprovider
– Vishal Arora
Nov 13 at 5:59
add a comment |
up vote
0
down vote
You need to add the following in provider declaration in your manifest file
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="<application-id>.fileprovider" // com.abc.def
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths" />
</provider>
I have already done the same as described link. One differance isandroid:authorities="<application-id>.fileprovider"
withandroid:authorities="$applicationId.my.package.name.provider"
Does it make any difference?
– Biswajit Das
Nov 12 at 16:52
You use this $applicationId.my.package.name.provider if you have a custom FileProvider class extending Android FileProvider class. If you dont have one then you need to use $applicationId.fileprovider
– Vishal Arora
Nov 13 at 5:59
add a comment |
up vote
0
down vote
up vote
0
down vote
You need to add the following in provider declaration in your manifest file
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="<application-id>.fileprovider" // com.abc.def
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths" />
</provider>
You need to add the following in provider declaration in your manifest file
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="<application-id>.fileprovider" // com.abc.def
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths" />
</provider>
answered Nov 12 at 6:40
Vishal Arora
963
963
I have already done the same as described link. One differance isandroid:authorities="<application-id>.fileprovider"
withandroid:authorities="$applicationId.my.package.name.provider"
Does it make any difference?
– Biswajit Das
Nov 12 at 16:52
You use this $applicationId.my.package.name.provider if you have a custom FileProvider class extending Android FileProvider class. If you dont have one then you need to use $applicationId.fileprovider
– Vishal Arora
Nov 13 at 5:59
add a comment |
I have already done the same as described link. One differance isandroid:authorities="<application-id>.fileprovider"
withandroid:authorities="$applicationId.my.package.name.provider"
Does it make any difference?
– Biswajit Das
Nov 12 at 16:52
You use this $applicationId.my.package.name.provider if you have a custom FileProvider class extending Android FileProvider class. If you dont have one then you need to use $applicationId.fileprovider
– Vishal Arora
Nov 13 at 5:59
I have already done the same as described link. One differance is
android:authorities="<application-id>.fileprovider"
with android:authorities="$applicationId.my.package.name.provider"
Does it make any difference?– Biswajit Das
Nov 12 at 16:52
I have already done the same as described link. One differance is
android:authorities="<application-id>.fileprovider"
with android:authorities="$applicationId.my.package.name.provider"
Does it make any difference?– Biswajit Das
Nov 12 at 16:52
You use this $applicationId.my.package.name.provider if you have a custom FileProvider class extending Android FileProvider class. If you dont have one then you need to use $applicationId.fileprovider
– Vishal Arora
Nov 13 at 5:59
You use this $applicationId.my.package.name.provider if you have a custom FileProvider class extending Android FileProvider class. If you dont have one then you need to use $applicationId.fileprovider
– Vishal Arora
Nov 13 at 5:59
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53255297%2fjava-lang-securityexception-permission-denial-writing-android-support-v4-conte%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown