diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 493d7f4d626..49e8977bfdb 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -1691,5 +1691,14 @@
+
+
+
diff --git a/res/xml/file_paths.xml b/res/xml/file_paths.xml
new file mode 100644
index 00000000000..294c0cbfc97
--- /dev/null
+++ b/res/xml/file_paths.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
diff --git a/src/com/android/settings/users/RestrictedProfileSettings.java b/src/com/android/settings/users/RestrictedProfileSettings.java
index 99e55ab5bca..73b49bfe193 100644
--- a/src/com/android/settings/users/RestrictedProfileSettings.java
+++ b/src/com/android/settings/users/RestrictedProfileSettings.java
@@ -20,6 +20,7 @@ import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.Fragment;
+import android.content.ClipData;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
@@ -27,14 +28,20 @@ import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.database.Cursor;
import android.graphics.Bitmap;
+import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.MediaStore;
import android.provider.ContactsContract.DisplayPhoto;
+import android.support.v4.content.FileProvider;
import android.text.TextUtils;
+import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -51,6 +58,8 @@ import android.widget.TextView;
import com.android.settings.R;
import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
@@ -58,6 +67,7 @@ public class RestrictedProfileSettings extends AppRestrictionsFragment {
private static final String KEY_SAVED_PHOTO = "pending_photo";
private static final int DIALOG_ID_EDIT_USER_INFO = 1;
+ public static final String FILE_PROVIDER_AUTHORITY = "com.android.settings.files";
private View mHeaderView;
private ImageView mUserIconView;
@@ -269,33 +279,20 @@ public class RestrictedProfileSettings extends AppRestrictionsFragment {
mNewUserPhotoDrawable = drawable;
}
- public boolean onActivityResult(int requestCode, int resultCode, final Intent data) {
+ public boolean onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode != Activity.RESULT_OK) {
return false;
}
+ final Uri pictureUri = data != null && data.getData() != null
+ ? data.getData() : mTakePictureUri;
switch (requestCode) {
+ case REQUEST_CODE_CROP_PHOTO:
+ onPhotoCropped(pictureUri, true);
+ return true;
+ case REQUEST_CODE_TAKE_PHOTO:
case REQUEST_CODE_CHOOSE_PHOTO:
- case REQUEST_CODE_CROP_PHOTO: {
- new AsyncTask() {
- @Override
- protected Bitmap doInBackground(Void... params) {
- return BitmapFactory.decodeFile(mCropPictureUri.getPath());
- }
- @Override
- protected void onPostExecute(Bitmap bitmap) {
- mNewUserPhotoBitmap = bitmap;
- mNewUserPhotoDrawable = CircleFramedDrawable
- .getInstance(mImageView.getContext(), mNewUserPhotoBitmap);
- mImageView.setImageDrawable(mNewUserPhotoDrawable);
- // Delete the files - not needed anymore.
- new File(mCropPictureUri.getPath()).delete();
- new File(mTakePictureUri.getPath()).delete();
- }
- }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null);
- } return true;
- case REQUEST_CODE_TAKE_PHOTO: {
- cropPhoto();
- } break;
+ cropPhoto(pictureUri);
+ return true;
}
return false;
}
@@ -380,24 +377,35 @@ public class RestrictedProfileSettings extends AppRestrictionsFragment {
private void takePhoto() {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
- intent.putExtra(MediaStore.EXTRA_OUTPUT, mTakePictureUri);
+ appendOutputExtra(intent, mTakePictureUri);
mFragment.startActivityForResult(intent, REQUEST_CODE_TAKE_PHOTO);
}
private void choosePhoto() {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT, null);
intent.setType("image/*");
- intent.putExtra(MediaStore.EXTRA_OUTPUT, mCropPictureUri);
- appendCropExtras(intent);
+ appendOutputExtra(intent, mTakePictureUri);
mFragment.startActivityForResult(intent, REQUEST_CODE_CHOOSE_PHOTO);
}
- private void cropPhoto() {
+ private void cropPhoto(Uri pictureUri) {
+ // TODO: Use a public intent, when there is one.
Intent intent = new Intent("com.android.camera.action.CROP");
- intent.setDataAndType(mTakePictureUri, "image/*");
- intent.putExtra(MediaStore.EXTRA_OUTPUT, mCropPictureUri);
+ intent.setDataAndType(pictureUri, "image/*");
+ appendOutputExtra(intent, mCropPictureUri);
appendCropExtras(intent);
- mFragment.startActivityForResult(intent, REQUEST_CODE_CROP_PHOTO);
+ if (intent.resolveActivity(mContext.getPackageManager()) != null) {
+ mFragment.startActivityForResult(intent, REQUEST_CODE_CROP_PHOTO);
+ } else {
+ onPhotoCropped(pictureUri, false);
+ }
+ }
+
+ private void appendOutputExtra(Intent intent, Uri pictureUri) {
+ intent.putExtra(MediaStore.EXTRA_OUTPUT, pictureUri);
+ intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION
+ | Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ intent.setClipData(ClipData.newRawUri(MediaStore.EXTRA_OUTPUT, pictureUri));
}
private void appendCropExtras(Intent intent) {
@@ -410,6 +418,63 @@ public class RestrictedProfileSettings extends AppRestrictionsFragment {
intent.putExtra("outputY", mPhotoSize);
}
+ private void onPhotoCropped(final Uri data, final boolean cropped) {
+ new AsyncTask() {
+ @Override
+ protected Bitmap doInBackground(Void... params) {
+ if (cropped) {
+ try {
+ InputStream imageStream = mContext.getContentResolver()
+ .openInputStream(data);
+ return BitmapFactory.decodeStream(imageStream);
+ } catch (FileNotFoundException fe) {
+ return null;
+ }
+ } else {
+ // Scale and crop to a square aspect ratio
+ Bitmap croppedImage = Bitmap.createBitmap(mPhotoSize, mPhotoSize,
+ Config.ARGB_8888);
+ Canvas canvas = new Canvas(croppedImage);
+ Bitmap fullImage = null;
+ try {
+ InputStream imageStream = mContext.getContentResolver()
+ .openInputStream(data);
+ fullImage = BitmapFactory.decodeStream(imageStream);
+ } catch (FileNotFoundException fe) {
+ return null;
+ }
+ if (fullImage != null) {
+ final int squareSize = Math.min(fullImage.getWidth(),
+ fullImage.getHeight());
+ final int left = (fullImage.getWidth() - squareSize) / 2;
+ final int top = (fullImage.getHeight() - squareSize) / 2;
+ Rect rectSource = new Rect(left, top,
+ left + squareSize, top + squareSize);
+ Rect rectDest = new Rect(0, 0, mPhotoSize, mPhotoSize);
+ Paint paint = new Paint();
+ canvas.drawBitmap(fullImage, rectSource, rectDest, paint);
+ return croppedImage;
+ } else {
+ // Bah! Got nothin.
+ return null;
+ }
+ }
+ }
+
+ @Override
+ protected void onPostExecute(Bitmap bitmap) {
+ if (bitmap != null) {
+ mNewUserPhotoBitmap = bitmap;
+ mNewUserPhotoDrawable = CircleFramedDrawable
+ .getInstance(mImageView.getContext(), mNewUserPhotoBitmap);
+ mImageView.setImageDrawable(mNewUserPhotoDrawable);
+ }
+ new File(mContext.getCacheDir(), TAKE_PICTURE_FILE_NAME).delete();
+ new File(mContext.getCacheDir(), CROP_PICTURE_FILE_NAME).delete();
+ }
+ }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null);
+ }
+
private static int getPhotoSize(Context context) {
Cursor cursor = context.getContentResolver().query(
DisplayPhoto.CONTENT_MAX_DIMENSIONS_URI,
@@ -423,11 +488,13 @@ public class RestrictedProfileSettings extends AppRestrictionsFragment {
}
private static Uri createTempImageUri(Context context, String fileName) {
- File folder = context.getExternalCacheDir();
+ final File folder = context.getCacheDir();
folder.mkdirs();
- File fullPath = new File(folder, fileName);
+ final File fullPath = new File(folder, fileName);
fullPath.delete();
- return Uri.fromFile(fullPath.getAbsoluteFile());
+ final Uri fileUri =
+ FileProvider.getUriForFile(context, FILE_PROVIDER_AUTHORITY, fullPath);
+ return fileUri;
}
private static final class AdapterItem {