Loading AndroidManifest.xml +12 −0 Original line number Diff line number Diff line Loading @@ -225,6 +225,18 @@ </intent-filter> </activity> <permission android:name="com.android.gallery3d.filtershow.permission.READ" android:protectionLevel="signature" /> <permission android:name="com.android.gallery3d.filtershow.permission.WRITE" android:protectionLevel="signature" /> <provider android:name="com.android.gallery3d.filtershow.provider.SharedImageProvider" android:authorities="com.android.gallery3d.filtershow.provider.SharedImageProvider" android:grantUriPermissions="true" android:readPermission="com.android.gallery3d.filtershow.permission.READ" android:writePermission="com.android.gallery3d.filtershow.permission.WRITE" /> <activity android:name="com.android.gallery3d.filtershow.FilterShowActivity" android:label="@string/title_activity_filter_show" Loading src/com/android/gallery3d/filtershow/FilterShowActivity.java +59 −8 Original line number Diff line number Diff line package com.android.gallery3d.filtershow; import java.io.File; import java.io.IOException; import java.util.Vector; import com.android.gallery3d.filtershow.cache.ImageLoader; Loading @@ -10,6 +12,8 @@ import com.android.gallery3d.filtershow.imageshow.ImageShow; import com.android.gallery3d.filtershow.imageshow.ImageSmallFilter; import com.android.gallery3d.filtershow.imageshow.ImageStraighten; import com.android.gallery3d.filtershow.presets.*; import com.android.gallery3d.filtershow.provider.SharedImageProvider; import com.android.gallery3d.filtershow.tools.SaveCopyTask; import com.android.gallery3d.filtershow.ui.ImageCurves; import com.android.gallery3d.R; Loading @@ -18,6 +22,7 @@ import android.os.Bundle; import android.annotation.TargetApi; import android.app.ActionBar; import android.app.Activity; import android.content.ContentValues; import android.content.Intent; import android.content.res.Resources; import android.graphics.drawable.Drawable; Loading @@ -31,7 +36,6 @@ import android.view.MotionEvent; import android.view.View; import android.view.View.OnClickListener; import android.view.View.OnTouchListener; import android.widget.AbsoluteLayout; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.Button; Loading @@ -40,10 +44,13 @@ import android.widget.FrameLayout.LayoutParams; import android.widget.ImageButton; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.ShareActionProvider; import android.widget.ShareActionProvider.OnShareTargetSelectedListener; import android.widget.Toast; @TargetApi(16) public class FilterShowActivity extends Activity implements OnItemClickListener { public class FilterShowActivity extends Activity implements OnItemClickListener, OnShareTargetSelectedListener { private ImageLoader mImageLoader = null; private ImageShow mImageShow = null; Loading Loading @@ -84,6 +91,11 @@ public class FilterShowActivity extends Activity implements OnItemClickListener private Vector<ImageButton> mBottomPanelButtons = new Vector<ImageButton>(); private Vector<ImageButton> mColorsPanelButtons = new Vector<ImageButton>(); private ShareActionProvider mShareActionProvider; private File mSharedOutputFile = null; private boolean mSharingImage = false; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Loading Loading @@ -210,6 +222,46 @@ public class FilterShowActivity extends Activity implements OnItemClickListener } } public void completeSaveImage(Uri saveUri) { if (mSharingImage && mSharedOutputFile != null) { // Image saved, we unblock the content provider Uri uri = Uri.withAppendedPath(SharedImageProvider.CONTENT_URI, Uri.encode(mSharedOutputFile.getAbsolutePath())); ContentValues values = new ContentValues(); values.put(SharedImageProvider.PREPARE, false); getContentResolver().insert(uri, values); } setResult(RESULT_OK, new Intent().setData(saveUri)); finish(); } @Override public boolean onShareTargetSelected(ShareActionProvider arg0, Intent arg1) { // First, let's tell the SharedImageProvider that it will need to wait for the image Uri uri = Uri.withAppendedPath(SharedImageProvider.CONTENT_URI, Uri.encode(mSharedOutputFile.getAbsolutePath())); ContentValues values = new ContentValues(); values.put(SharedImageProvider.PREPARE, true); getContentResolver().insert(uri, values); mSharingImage = true; // Process and save the image in the background. mImageShow.saveImage(this, mSharedOutputFile); return true; } private Intent getDefaultShareIntent() { Intent intent = new Intent(Intent.ACTION_SEND); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); intent.setType(SharedImageProvider.MIME_TYPE); mSharedOutputFile = SaveCopyTask.getNewFile(this, mImageLoader.getUri()); Uri uri = Uri.withAppendedPath(SharedImageProvider.CONTENT_URI, Uri.encode(mSharedOutputFile.getAbsolutePath())); intent.putExtra(Intent.EXTRA_STREAM, uri); return intent; } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.filtershow_activity_menu, menu); Loading @@ -225,6 +277,10 @@ public class FilterShowActivity extends Activity implements OnItemClickListener } else { showState.setTitle(R.string.show_imagestate_panel); } mShareActionProvider = (ShareActionProvider) menu.findItem(R.id.menu_share) .getActionProvider(); mShareActionProvider.setShareIntent(getDefaultShareIntent()); mShareActionProvider.setOnShareTargetSelectedListener(this); return true; } Loading Loading @@ -865,12 +921,7 @@ public class FilterShowActivity extends Activity implements OnItemClickListener toast.setGravity(Gravity.CENTER, 0, 0); toast.show(); mImageShow.saveImage(this); } public void completeSaveImage(Uri saveUri) { setResult(RESULT_OK, new Intent().setData(saveUri)); finish(); mImageShow.saveImage(this, null); } static { Loading src/com/android/gallery3d/filtershow/cache/ImageLoader.java +11 −4 Original line number Diff line number Diff line Loading @@ -2,6 +2,7 @@ package com.android.gallery3d.filtershow.cache; import java.io.Closeable; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; Loading @@ -13,6 +14,7 @@ import com.android.gallery3d.filtershow.HistoryAdapter; import com.android.gallery3d.filtershow.imageshow.ImageShow; import com.android.gallery3d.filtershow.presets.ImagePreset; import com.android.gallery3d.filtershow.tools.SaveCopyTask; import com.android.gallery3d.filtershow.tools.ProcessedBitmap; import com.android.gallery3d.R; import android.content.Context; Loading Loading @@ -59,6 +61,10 @@ public class ImageLoader { updateBitmaps(); } public Uri getUri() { return mUri; } private int getOrientation(Uri uri) { Cursor cursor = null; try { Loading Loading @@ -219,7 +225,8 @@ public class ImageLoader { mCache.reset(imagePreset); } public Uri saveImage(ImagePreset preset, final FilterShowActivity filterShowActivity) { public Uri saveImage(ImagePreset preset, final FilterShowActivity filterShowActivity, File destination) { BitmapFactory.Options options = new BitmapFactory.Options(); options.inMutable = true; Loading @@ -235,15 +242,15 @@ public class ImageLoader { // TODO: on <3.x we need a copy of the bitmap (inMutable doesn't // exist) mSaveCopy = mFullOriginalBitmap; preset.apply(mSaveCopy); new SaveCopyTask(mContext, mUri, new SaveCopyTask.Callback() { ProcessedBitmap processedBitmap = new ProcessedBitmap(mSaveCopy, preset); new SaveCopyTask(mContext, mUri, destination, new SaveCopyTask.Callback() { @Override public void onComplete(Uri result) { filterShowActivity.completeSaveImage(result); } }).execute(mSaveCopy); }).execute(processedBitmap); } catch (FileNotFoundException e) { e.printStackTrace(); } finally { Loading src/com/android/gallery3d/filtershow/imageshow/ImageShow.java +4 −2 Original line number Diff line number Diff line Loading @@ -13,6 +13,8 @@ import com.android.gallery3d.R; import com.android.gallery3d.R.id; import com.android.gallery3d.R.layout; import java.io.File; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; Loading Loading @@ -288,8 +290,8 @@ public class ImageShow extends View implements SliderListener { mFilteredImage = bitmap; } public void saveImage(FilterShowActivity filterShowActivity) { mImageLoader.saveImage(getImagePreset(), filterShowActivity); public void saveImage(FilterShowActivity filterShowActivity, File file) { mImageLoader.saveImage(getImagePreset(), filterShowActivity, file); } public boolean onTouchEvent(MotionEvent event) { Loading src/com/android/gallery3d/filtershow/provider/SharedImageProvider.java 0 → 100644 +123 −0 Original line number Diff line number Diff line package com.android.gallery3d.filtershow.provider; import android.content.ContentProvider; import android.content.ContentValues; import android.database.Cursor; import android.database.MatrixCursor; import android.net.Uri; import android.os.ConditionVariable; import android.os.ParcelFileDescriptor; import android.provider.BaseColumns; import android.provider.MediaStore; import android.provider.OpenableColumns; import android.util.Log; import java.io.File; import java.io.FileNotFoundException; import java.util.Arrays; public class SharedImageProvider extends ContentProvider { private static final String LOGTAG = "SharedImageProvider"; public static final String MIME_TYPE = "image/jpeg"; public static final String AUTHORITY = "com.android.gallery3d.filtershow.provider.SharedImageProvider"; public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/image"); public static final String PREPARE = "prepare"; private final String[] mMimeStreamType = { MIME_TYPE }; private static ConditionVariable mImageReadyCond = new ConditionVariable(false); @Override public int delete(Uri arg0, String arg1, String[] arg2) { return 0; } @Override public String getType(Uri arg0) { return MIME_TYPE; } @Override public String[] getStreamTypes(Uri arg0, String mimeTypeFilter) { return mMimeStreamType; } @Override public Uri insert(Uri uri, ContentValues values) { if (values.containsKey(PREPARE)) { if (values.getAsBoolean(PREPARE)) { mImageReadyCond.close(); } else { mImageReadyCond.open(); } } return null; } @Override public int update(Uri arg0, ContentValues arg1, String arg2, String[] arg3) { return 0; } @Override public boolean onCreate() { return true; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { String uriPath = uri.getLastPathSegment(); if (uriPath == null) { return null; } if (projection == null) { projection = new String[] { BaseColumns._ID, MediaStore.MediaColumns.DATA, OpenableColumns.DISPLAY_NAME, OpenableColumns.SIZE }; } // If we receive a query on display name or size, // we should block until the image is ready mImageReadyCond.block(); File path = new File(uriPath); MatrixCursor cursor = new MatrixCursor(projection); Object[] columns = new Object[projection.length]; for (int i = 0; i < projection.length; i++) { if (projection[i].equalsIgnoreCase(BaseColumns._ID)) { columns[i] = 0; } else if (projection[i].equalsIgnoreCase(MediaStore.MediaColumns.DATA)) { columns[i] = uri; } else if (projection[i].equalsIgnoreCase(OpenableColumns.DISPLAY_NAME)) { columns[i] = path.getName(); } else if (projection[i].equalsIgnoreCase(OpenableColumns.SIZE)) { columns[i] = path.length(); } } cursor.addRow(columns); return cursor; } public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException { String uriPath = uri.getLastPathSegment(); if (uriPath == null) { return null; } // Here we need to block until the image is ready mImageReadyCond.block(); File path = new File(uriPath); int imode = 0; imode |= ParcelFileDescriptor.MODE_READ_ONLY; return ParcelFileDescriptor.open(path, imode); } } Loading
AndroidManifest.xml +12 −0 Original line number Diff line number Diff line Loading @@ -225,6 +225,18 @@ </intent-filter> </activity> <permission android:name="com.android.gallery3d.filtershow.permission.READ" android:protectionLevel="signature" /> <permission android:name="com.android.gallery3d.filtershow.permission.WRITE" android:protectionLevel="signature" /> <provider android:name="com.android.gallery3d.filtershow.provider.SharedImageProvider" android:authorities="com.android.gallery3d.filtershow.provider.SharedImageProvider" android:grantUriPermissions="true" android:readPermission="com.android.gallery3d.filtershow.permission.READ" android:writePermission="com.android.gallery3d.filtershow.permission.WRITE" /> <activity android:name="com.android.gallery3d.filtershow.FilterShowActivity" android:label="@string/title_activity_filter_show" Loading
src/com/android/gallery3d/filtershow/FilterShowActivity.java +59 −8 Original line number Diff line number Diff line package com.android.gallery3d.filtershow; import java.io.File; import java.io.IOException; import java.util.Vector; import com.android.gallery3d.filtershow.cache.ImageLoader; Loading @@ -10,6 +12,8 @@ import com.android.gallery3d.filtershow.imageshow.ImageShow; import com.android.gallery3d.filtershow.imageshow.ImageSmallFilter; import com.android.gallery3d.filtershow.imageshow.ImageStraighten; import com.android.gallery3d.filtershow.presets.*; import com.android.gallery3d.filtershow.provider.SharedImageProvider; import com.android.gallery3d.filtershow.tools.SaveCopyTask; import com.android.gallery3d.filtershow.ui.ImageCurves; import com.android.gallery3d.R; Loading @@ -18,6 +22,7 @@ import android.os.Bundle; import android.annotation.TargetApi; import android.app.ActionBar; import android.app.Activity; import android.content.ContentValues; import android.content.Intent; import android.content.res.Resources; import android.graphics.drawable.Drawable; Loading @@ -31,7 +36,6 @@ import android.view.MotionEvent; import android.view.View; import android.view.View.OnClickListener; import android.view.View.OnTouchListener; import android.widget.AbsoluteLayout; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.Button; Loading @@ -40,10 +44,13 @@ import android.widget.FrameLayout.LayoutParams; import android.widget.ImageButton; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.ShareActionProvider; import android.widget.ShareActionProvider.OnShareTargetSelectedListener; import android.widget.Toast; @TargetApi(16) public class FilterShowActivity extends Activity implements OnItemClickListener { public class FilterShowActivity extends Activity implements OnItemClickListener, OnShareTargetSelectedListener { private ImageLoader mImageLoader = null; private ImageShow mImageShow = null; Loading Loading @@ -84,6 +91,11 @@ public class FilterShowActivity extends Activity implements OnItemClickListener private Vector<ImageButton> mBottomPanelButtons = new Vector<ImageButton>(); private Vector<ImageButton> mColorsPanelButtons = new Vector<ImageButton>(); private ShareActionProvider mShareActionProvider; private File mSharedOutputFile = null; private boolean mSharingImage = false; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Loading Loading @@ -210,6 +222,46 @@ public class FilterShowActivity extends Activity implements OnItemClickListener } } public void completeSaveImage(Uri saveUri) { if (mSharingImage && mSharedOutputFile != null) { // Image saved, we unblock the content provider Uri uri = Uri.withAppendedPath(SharedImageProvider.CONTENT_URI, Uri.encode(mSharedOutputFile.getAbsolutePath())); ContentValues values = new ContentValues(); values.put(SharedImageProvider.PREPARE, false); getContentResolver().insert(uri, values); } setResult(RESULT_OK, new Intent().setData(saveUri)); finish(); } @Override public boolean onShareTargetSelected(ShareActionProvider arg0, Intent arg1) { // First, let's tell the SharedImageProvider that it will need to wait for the image Uri uri = Uri.withAppendedPath(SharedImageProvider.CONTENT_URI, Uri.encode(mSharedOutputFile.getAbsolutePath())); ContentValues values = new ContentValues(); values.put(SharedImageProvider.PREPARE, true); getContentResolver().insert(uri, values); mSharingImage = true; // Process and save the image in the background. mImageShow.saveImage(this, mSharedOutputFile); return true; } private Intent getDefaultShareIntent() { Intent intent = new Intent(Intent.ACTION_SEND); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); intent.setType(SharedImageProvider.MIME_TYPE); mSharedOutputFile = SaveCopyTask.getNewFile(this, mImageLoader.getUri()); Uri uri = Uri.withAppendedPath(SharedImageProvider.CONTENT_URI, Uri.encode(mSharedOutputFile.getAbsolutePath())); intent.putExtra(Intent.EXTRA_STREAM, uri); return intent; } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.filtershow_activity_menu, menu); Loading @@ -225,6 +277,10 @@ public class FilterShowActivity extends Activity implements OnItemClickListener } else { showState.setTitle(R.string.show_imagestate_panel); } mShareActionProvider = (ShareActionProvider) menu.findItem(R.id.menu_share) .getActionProvider(); mShareActionProvider.setShareIntent(getDefaultShareIntent()); mShareActionProvider.setOnShareTargetSelectedListener(this); return true; } Loading Loading @@ -865,12 +921,7 @@ public class FilterShowActivity extends Activity implements OnItemClickListener toast.setGravity(Gravity.CENTER, 0, 0); toast.show(); mImageShow.saveImage(this); } public void completeSaveImage(Uri saveUri) { setResult(RESULT_OK, new Intent().setData(saveUri)); finish(); mImageShow.saveImage(this, null); } static { Loading
src/com/android/gallery3d/filtershow/cache/ImageLoader.java +11 −4 Original line number Diff line number Diff line Loading @@ -2,6 +2,7 @@ package com.android.gallery3d.filtershow.cache; import java.io.Closeable; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; Loading @@ -13,6 +14,7 @@ import com.android.gallery3d.filtershow.HistoryAdapter; import com.android.gallery3d.filtershow.imageshow.ImageShow; import com.android.gallery3d.filtershow.presets.ImagePreset; import com.android.gallery3d.filtershow.tools.SaveCopyTask; import com.android.gallery3d.filtershow.tools.ProcessedBitmap; import com.android.gallery3d.R; import android.content.Context; Loading Loading @@ -59,6 +61,10 @@ public class ImageLoader { updateBitmaps(); } public Uri getUri() { return mUri; } private int getOrientation(Uri uri) { Cursor cursor = null; try { Loading Loading @@ -219,7 +225,8 @@ public class ImageLoader { mCache.reset(imagePreset); } public Uri saveImage(ImagePreset preset, final FilterShowActivity filterShowActivity) { public Uri saveImage(ImagePreset preset, final FilterShowActivity filterShowActivity, File destination) { BitmapFactory.Options options = new BitmapFactory.Options(); options.inMutable = true; Loading @@ -235,15 +242,15 @@ public class ImageLoader { // TODO: on <3.x we need a copy of the bitmap (inMutable doesn't // exist) mSaveCopy = mFullOriginalBitmap; preset.apply(mSaveCopy); new SaveCopyTask(mContext, mUri, new SaveCopyTask.Callback() { ProcessedBitmap processedBitmap = new ProcessedBitmap(mSaveCopy, preset); new SaveCopyTask(mContext, mUri, destination, new SaveCopyTask.Callback() { @Override public void onComplete(Uri result) { filterShowActivity.completeSaveImage(result); } }).execute(mSaveCopy); }).execute(processedBitmap); } catch (FileNotFoundException e) { e.printStackTrace(); } finally { Loading
src/com/android/gallery3d/filtershow/imageshow/ImageShow.java +4 −2 Original line number Diff line number Diff line Loading @@ -13,6 +13,8 @@ import com.android.gallery3d.R; import com.android.gallery3d.R.id; import com.android.gallery3d.R.layout; import java.io.File; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; Loading Loading @@ -288,8 +290,8 @@ public class ImageShow extends View implements SliderListener { mFilteredImage = bitmap; } public void saveImage(FilterShowActivity filterShowActivity) { mImageLoader.saveImage(getImagePreset(), filterShowActivity); public void saveImage(FilterShowActivity filterShowActivity, File file) { mImageLoader.saveImage(getImagePreset(), filterShowActivity, file); } public boolean onTouchEvent(MotionEvent event) { Loading
src/com/android/gallery3d/filtershow/provider/SharedImageProvider.java 0 → 100644 +123 −0 Original line number Diff line number Diff line package com.android.gallery3d.filtershow.provider; import android.content.ContentProvider; import android.content.ContentValues; import android.database.Cursor; import android.database.MatrixCursor; import android.net.Uri; import android.os.ConditionVariable; import android.os.ParcelFileDescriptor; import android.provider.BaseColumns; import android.provider.MediaStore; import android.provider.OpenableColumns; import android.util.Log; import java.io.File; import java.io.FileNotFoundException; import java.util.Arrays; public class SharedImageProvider extends ContentProvider { private static final String LOGTAG = "SharedImageProvider"; public static final String MIME_TYPE = "image/jpeg"; public static final String AUTHORITY = "com.android.gallery3d.filtershow.provider.SharedImageProvider"; public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/image"); public static final String PREPARE = "prepare"; private final String[] mMimeStreamType = { MIME_TYPE }; private static ConditionVariable mImageReadyCond = new ConditionVariable(false); @Override public int delete(Uri arg0, String arg1, String[] arg2) { return 0; } @Override public String getType(Uri arg0) { return MIME_TYPE; } @Override public String[] getStreamTypes(Uri arg0, String mimeTypeFilter) { return mMimeStreamType; } @Override public Uri insert(Uri uri, ContentValues values) { if (values.containsKey(PREPARE)) { if (values.getAsBoolean(PREPARE)) { mImageReadyCond.close(); } else { mImageReadyCond.open(); } } return null; } @Override public int update(Uri arg0, ContentValues arg1, String arg2, String[] arg3) { return 0; } @Override public boolean onCreate() { return true; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { String uriPath = uri.getLastPathSegment(); if (uriPath == null) { return null; } if (projection == null) { projection = new String[] { BaseColumns._ID, MediaStore.MediaColumns.DATA, OpenableColumns.DISPLAY_NAME, OpenableColumns.SIZE }; } // If we receive a query on display name or size, // we should block until the image is ready mImageReadyCond.block(); File path = new File(uriPath); MatrixCursor cursor = new MatrixCursor(projection); Object[] columns = new Object[projection.length]; for (int i = 0; i < projection.length; i++) { if (projection[i].equalsIgnoreCase(BaseColumns._ID)) { columns[i] = 0; } else if (projection[i].equalsIgnoreCase(MediaStore.MediaColumns.DATA)) { columns[i] = uri; } else if (projection[i].equalsIgnoreCase(OpenableColumns.DISPLAY_NAME)) { columns[i] = path.getName(); } else if (projection[i].equalsIgnoreCase(OpenableColumns.SIZE)) { columns[i] = path.length(); } } cursor.addRow(columns); return cursor; } public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException { String uriPath = uri.getLastPathSegment(); if (uriPath == null) { return null; } // Here we need to block until the image is ready mImageReadyCond.block(); File path = new File(uriPath); int imode = 0; imode |= ParcelFileDescriptor.MODE_READ_ONLY; return ParcelFileDescriptor.open(path, imode); } }