Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ea3de483 authored by Danesh M's avatar Danesh M
Browse files

Gallery3d : 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.

issue-id: CYNGNOS-897

Change-Id: I9ec8b8defaffa3d9fa0c2cdfd68422eeff5aef84
(cherry picked from commit a5aa75d6)
parent 26df7c66
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -436,5 +436,14 @@
                android:label="@string/movie_view_label"
                android:configChanges="orientation|keyboardHidden|screenSize|mnc|mcc">
        </activity>
        <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>

res/xml/file_paths.xml

0 → 100644
+18 −0
Original line number Diff line number Diff line
<!--
     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>
+9 −1
Original line number Diff line number Diff line
@@ -233,6 +233,14 @@
            </intent-filter>
        </activity>
        <service android:name="com.android.gallery3d.app.BatchService" />

        <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>
+1 −1
Original line number Diff line number Diff line
@@ -108,7 +108,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;
+142 −34
Original line number Diff line number Diff line
@@ -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,16 +130,43 @@ 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));
@@ -133,8 +174,13 @@ public class WidgetConfigure extends Activity {
                    helper.close();
                }
            }
        });
    }

    private void setChoosenPhoto(Intent data) {
    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);
@@ -148,17 +194,79 @@ public class WidgetConfigure extends Activity {
                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();
        Intent request = new Intent(CropActivity.CROP_ACTION, mPickedItem)
                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, 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 {
            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 {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    // ignore
                }
            }
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    // ignore
                }
            }
        }
        return isSuccessful;
    }

    private void setChoosenAlbum(Intent data) {
        String albumPath = data.getStringExtra(AlbumPicker.KEY_ALBUM_PATH);