diff options
author | Danesh M <daneshm90@gmail.com> | 2015-09-09 17:51:27 -0700 |
---|---|---|
committer | Arne Coucheron <arco68@gmail.com> | 2017-03-10 07:20:04 +0100 |
commit | 0393ad5f1c4a540a409429c09a5ec98e3bdd5b8f (patch) | |
tree | f7b670f0b1f252aa69b8648cf40227c45a5e1aba | |
parent | c098de9d87ab43746160e479d57a8028890d532b (diff) | |
download | android_packages_apps_Gallery2-0393ad5f1c4a540a409429c09a5ec98e3bdd5b8f.tar.gz android_packages_apps_Gallery2-0393ad5f1c4a540a409429c09a5ec98e3bdd5b8f.tar.bz2 android_packages_apps_Gallery2-0393ad5f1c4a540a409429c09a5ec98e3bdd5b8f.zip |
Gallery2: Fix CROP_ACTION for third party apps
Certain apps such as google photos, don't respect
return-data true, since the bitmap could be very large.
Switch to a file provider to pass the external apps a uri
to write cropped results to.
Change-Id: I9ec8b8defaffa3d9fa0c2cdfd68422eeff5aef84
-rwxr-xr-x | AndroidManifest.xml | 9 | ||||
-rw-r--r-- | res/xml/file_paths.xml | 18 | ||||
-rw-r--r-- | src/com/android/gallery3d/filtershow/cache/ImageLoader.java | 2 | ||||
-rw-r--r-- | src/com/android/gallery3d/gadget/WidgetConfigure.java | 176 |
4 files changed, 170 insertions, 35 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 5ddebcc76..2c3f08d8e 100755 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -411,5 +411,14 @@ android:configChanges="orientation|keyboardHidden|screenSize|mnc|mcc"> </activity> <activity android:name="com.android.gallery3d.app.dualcam3d.ThreeDimensionalActivity"/> + <provider + android:name="android.support.v4.content.FileProvider" + android:authorities="com.android.gallery3d.fileprovider" + android:exported="false" + android:grantUriPermissions="true"> + <meta-data + android:name="android.support.FILE_PROVIDER_PATHS" + android:resource="@xml/file_paths" /> + </provider> </application> </manifest> diff --git a/res/xml/file_paths.xml b/res/xml/file_paths.xml new file mode 100644 index 000000000..28d186477 --- /dev/null +++ b/res/xml/file_paths.xml @@ -0,0 +1,18 @@ +<!-- + Copyright (C) 2012-2015 The CyanogenMod Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<paths xmlns:android="http://schemas.android.com/apk/res/android"> + <cache-path name="cropped_image"/> +</paths> diff --git a/src/com/android/gallery3d/filtershow/cache/ImageLoader.java b/src/com/android/gallery3d/filtershow/cache/ImageLoader.java index d8560312c..ef307d9c4 100644 --- a/src/com/android/gallery3d/filtershow/cache/ImageLoader.java +++ b/src/com/android/gallery3d/filtershow/cache/ImageLoader.java @@ -107,7 +107,7 @@ public final class ImageLoader { new String[] { MediaStore.Images.ImageColumns.ORIENTATION }, null, null, null); if (cursor != null && cursor.moveToNext()) { - int ori = cursor.getInt(0); + int ori = cursor.getColumnIndexOrThrow(MediaStore.Images.ImageColumns.ORIENTATION); switch (ori) { case 90: return ORI_ROTATE_90; diff --git a/src/com/android/gallery3d/gadget/WidgetConfigure.java b/src/com/android/gallery3d/gadget/WidgetConfigure.java index f674f3038..43175b6de 100644 --- a/src/com/android/gallery3d/gadget/WidgetConfigure.java +++ b/src/com/android/gallery3d/gadget/WidgetConfigure.java @@ -18,11 +18,16 @@ package com.android.gallery3d.gadget; import android.app.Activity; import android.appwidget.AppWidgetManager; +import android.content.ClipData; import android.content.Intent; import android.content.res.Resources; import android.graphics.Bitmap; +import android.graphics.BitmapFactory; import android.net.Uri; +import android.os.AsyncTask; import android.os.Bundle; +import android.provider.MediaStore; +import android.support.v4.content.FileProvider; import android.util.Log; import android.widget.RemoteViews; @@ -38,6 +43,14 @@ import com.android.gallery3d.data.Path; import com.android.gallery3d.filtershow.crop.CropActivity; import com.android.gallery3d.filtershow.crop.CropExtras; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + public class WidgetConfigure extends Activity { @SuppressWarnings("unused") private static final String TAG = "WidgetConfigure"; @@ -61,6 +74,7 @@ public class WidgetConfigure extends Activity { private int mAppWidgetId = -1; private Uri mPickedItem; + private Uri mCropSrc, mCropDst; @Override protected void onCreate(Bundle savedState) { @@ -116,48 +130,142 @@ public class WidgetConfigure extends Activity { } else if (requestCode == REQUEST_GET_PHOTO) { setChoosenPhoto(data); } else if (requestCode == REQUEST_CROP_IMAGE) { - setPhotoWidget(data); + setPhotoWidget(); } else { throw new AssertionError("unknown request: " + requestCode); } } - private void setPhotoWidget(Intent data) { - // Store the cropped photo in our database - Bitmap bitmap = (Bitmap) data.getParcelableExtra("data"); - WidgetDatabaseHelper helper = new WidgetDatabaseHelper(this); + private void setPhotoWidget() { + AsyncTask.execute(new Runnable() { + @Override + public void run() { + Bitmap bitmap = null; + InputStream stream = null; + try { + stream = WidgetConfigure.this.getContentResolver() + .openInputStream(mCropDst); + if (stream != null) { + bitmap = BitmapFactory.decodeStream(stream); + } + } catch (FileNotFoundException e) { + e.printStackTrace(); + } finally { + if (stream != null) { + try { + stream.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + getContentResolver().delete(mCropSrc, null, null); + getContentResolver().delete(mCropDst, null, null); + } + if (bitmap == null) { + setResult(Activity.RESULT_CANCELED); + finish(); + return; + } + WidgetDatabaseHelper helper = new WidgetDatabaseHelper(WidgetConfigure.this); + try { + helper.setPhoto(mAppWidgetId, mPickedItem, bitmap); + updateWidgetAndFinish(helper.getEntry(mAppWidgetId)); + } finally { + helper.close(); + } + } + }); + } + + private void setChoosenPhoto(final Intent data) { + AsyncTask.execute(new Runnable() { + @Override + public void run() { + Resources res = getResources(); + + float width = res.getDimension(R.dimen.appwidget_width); + float height = res.getDimension(R.dimen.appwidget_height); + + // We try to crop a larger image (by scale factor), but there is still + // a bound on the binder limit. + float scale = Math.min(WIDGET_SCALE_FACTOR, + MAX_WIDGET_SIDE / Math.max(width, height)); + + int widgetWidth = Math.round(width * scale); + int widgetHeight = Math.round(height * scale); + + File cropSrc = new File(getCacheDir(), "crop_source.png"); + File cropDst = new File(getCacheDir(), "crop_dest.png"); + mPickedItem = data.getData(); + if (!copyUriToFile(mPickedItem, cropSrc)) { + setResult(Activity.RESULT_CANCELED); + finish(); + return; + } + + mCropSrc = FileProvider.getUriForFile(WidgetConfigure.this, + "com.android.gallery3d.fileprovider", + new File(cropSrc.getAbsolutePath())); + mCropDst = FileProvider.getUriForFile(WidgetConfigure.this, + "com.android.gallery3d.fileprovider", + new File(cropDst.getAbsolutePath())); + + Intent request = new Intent(CropActivity.CROP_ACTION) + .putExtra(CropExtras.KEY_OUTPUT_X, widgetWidth) + .putExtra(CropExtras.KEY_OUTPUT_Y, widgetHeight) + .putExtra(CropExtras.KEY_ASPECT_X, widgetWidth) + .putExtra(CropExtras.KEY_ASPECT_Y, widgetHeight) + .putExtra(CropExtras.KEY_SCALE_UP_IF_NEEDED, true) + .putExtra(CropExtras.KEY_SCALE, true) + .putExtra(CropExtras.KEY_RETURN_DATA, false) + .setDataAndType(mCropSrc, "image/*") + .addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION | + Intent.FLAG_GRANT_READ_URI_PERMISSION); + request.putExtra(MediaStore.EXTRA_OUTPUT, mCropDst); + request.setClipData(ClipData.newRawUri(MediaStore.EXTRA_OUTPUT, mCropDst)); + startActivityForResult(request, REQUEST_CROP_IMAGE); + } + }); + } + + public boolean copyUriToFile(Uri inUri, File dst) { + boolean isSuccessful = false; + InputStream in = null; + OutputStream out = null; try { - helper.setPhoto(mAppWidgetId, mPickedItem, bitmap); - updateWidgetAndFinish(helper.getEntry(mAppWidgetId)); + in = getContentResolver().openInputStream(inUri); + out = new FileOutputStream(dst); + + byte[] buf = new byte[1024]; + + try { + for (int len; (len = in.read(buf)) > 0; ) { + out.write(buf, 0, len); + } + isSuccessful = true; + } catch (IOException e) { + // ignore + } + + } catch (FileNotFoundException fnf) { + // ignore } finally { - helper.close(); + if (in != null) { + try { + in.close(); + } catch (IOException e) { + // ignore + } + } + if (out != null) { + try { + out.close(); + } catch (IOException e) { + // ignore + } + } } - } - - private void setChoosenPhoto(Intent data) { - Resources res = getResources(); - - float width = res.getDimension(R.dimen.appwidget_width); - float height = res.getDimension(R.dimen.appwidget_height); - - // We try to crop a larger image (by scale factor), but there is still - // a bound on the binder limit. - float scale = Math.min(WIDGET_SCALE_FACTOR, - MAX_WIDGET_SIDE / Math.max(width, height)); - - int widgetWidth = Math.round(width * scale); - int widgetHeight = Math.round(height * scale); - - mPickedItem = data.getData(); - Intent request = new Intent(CropActivity.CROP_ACTION, mPickedItem) - .putExtra(CropExtras.KEY_OUTPUT_X, widgetWidth) - .putExtra(CropExtras.KEY_OUTPUT_Y, widgetHeight) - .putExtra(CropExtras.KEY_ASPECT_X, widgetWidth) - .putExtra(CropExtras.KEY_ASPECT_Y, widgetHeight) - .putExtra(CropExtras.KEY_SCALE_UP_IF_NEEDED, true) - .putExtra(CropExtras.KEY_SCALE, true) - .putExtra(CropExtras.KEY_RETURN_DATA, true); - startActivityForResult(request, REQUEST_CROP_IMAGE); + return isSuccessful; } private void setChoosenAlbum(Intent data) { |