I am trying to run PhotoStream sample from following link
http://android-developers.blogspot.com/2008/09/android-photostream.html
Just Remove:
intent.setClassName("com.android.camera", "com.android.camera.CropImage");
it will ask from which application you want to crop image.
An alternative is to let the application save the picture first and manually crop it, i.e.:
Intent intentPick = new Intent("com.android.camera.action.CROP");
intentPick.setClassName("com.android.camera", "com.android.camera.CropImage");//TODO fails in Android 2.x
List<ResolveInfo> list = getPackageManager().queryIntentActivities(intentPick, PackageManager.MATCH_DEFAULT_ONLY);
if (list.size() > 0)
{
intentPick.setData(selectedImageCropped);
intentPick.putExtra("outputX", 240);
intentPick.putExtra("outputY", 240);
intentPick.putExtra("aspectX", 1);
intentPick.putExtra("aspectY", 1);
intentPick.putExtra("scale", true);
intentPick.putExtra("noFaceDetection", true);
intentPick.putExtra(MediaStore.EXTRA_OUTPUT, selectedImageCropped);
startActivityForResult(intentPick, PROCESS_IMAGE);
}
else
{
Log.w(Tag, "PHOTO CROPPING IS INDEED NOT SUPPORTED.");
startActivityForResult(new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI), FROM_IMAGE_SELECT);
Toast.makeText(ContactAdder.this, R.string.select_image_from_sdcard_string, Toast.LENGTH_SHORT).show();
}
A success result leads to:
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == Activity.RESULT_OK)
{
switch (requestCode)
{
case FROM_IMAGE_SELECT:
selectedImageCropped = Uri.fromFile(new File(Environment.getExternalStorageDirectory(), "TEMP_IMAGE_" + String.valueOf(System.currentTimeMillis()) + ".jpg"));
/** Crop selected image. */
final Intent intentSelect = new Intent("com.android.camera.action.CROP");
intentSelect.setData(data.getData());
intentSelect.putExtra("outputX", 240);
intentSelect.putExtra("outputY", 240);
intentSelect.putExtra("aspectX", 1);
intentSelect.putExtra("aspectY", 1);
intentSelect.putExtra("scale", true);
intentSelect.putExtra("noFaceDetection", true);
intentSelect.putExtra("output", selectedImageCropped);
startActivityForResult(intentSelect, PROCESS_IMAGE);
break;
And then process your cropped image.
I remember reading that this was an undocumented feature and doesn't exist in any API. It is now not accessible in 2.x
If there is no constant in the SDK for the string "com.android.camera.action.CROP" then this is simply not a part of the SDK, and has a chance of breaking in the future
You can bundle the CropImage
activity with your app package so it is independent on Android version.
Here's the project: https://github.com/lvillani/android-cropimage
The CropImage activity extracted from Gallery.apk (AOSP 4.4.4). Compatible with Android API Level 15 and up.
Remember to add the following line to your AndroidManifest.xml
:
<!-- Declare the bundled CropImage Activity -->
<activity android:name="com.android.camera.CropImage"/>
Actually there are quite a few apps, which offer the CROP action in Android 2.x: the standard Gallery, or Flikie Wallpapers just to name a couple. Why resolving the intents successfully fails, is that Google changed the components which provide the API. In Android 1.x that might have been com.android.gallery, but since (I think) API9/Android 2.3.x the default gallery is provided by Cooliris, so it is something like com.cooliris.gallery, etc.
The correct way to resolve the intent on any phone is (code, which I use):
// this is something to keep our information
class CropOption
{
CharSequence TITLE;
Drawable ICON;
Intent CROP_APP;
}
// we will present the available selection in a list dialog, so we need an adapter
class CropOptionAdapter extends ArrayAdapter<CropOption>
{
private List<CropOption> _items;
private Context _ctx;
CropOptionAdapter(Context ctx, List<CropOption> items)
{
super(ctx, R.layout.crop_option, items);
_items = items;
_ctx = ctx;
}
@Override
public View getView( int position, View convertView, ViewGroup parent )
{
if ( convertView == null )
convertView = LayoutInflater.from( _ctx ).inflate( R.layout.crop_option, null );
CropOption item = _items.get( position );
if ( item != null )
{
( ( ImageView ) convertView.findViewById( R.id.crop_icon ) ).setImageDrawable( item.ICON );
( ( TextView ) convertView.findViewById( R.id.crop_name ) ).setText( item.TITLE );
return convertView;
}
return null;
}
}
The layout for the item should be a horizontal linear layout with an IconView and a TextView. I will skip it for brevity's sake, by now you most probably know how to do it :-)
Now for the part where we find the intents and present them for selection (this is only the relevant part of the function, onActivityResult):
try
{
final List<CropOption> cropOptions = new ArrayList<CropOption>();
// this 2 lines are all you need to find the intent!!!
Intent intent = new Intent( "com.android.camera.action.CROP" );
intent.setType( "image/*" );
List<ResolveInfo> list = getPackageManager().queryIntentActivities( intent, 0 );
if ( list.size() == 0 )
{
// I tend to put any kind of text to be presented to the user as a resource for easier translation (if it ever comes to that...)
Toast.makeText( this, getText( R.string.error_crop_option ), Toast.LENGTH_LONG );
// this is the URI returned from the camera, it could be a file or a content URI, the crop app will take any
_captureUri = null; // leave the picture there
break; // leave this switch case...
}
intent.setData( _captureUri );
intent.putExtra( "outputX", 128 );
intent.putExtra( "outputY", 128 );
intent.putExtra( "aspectX", 1 );
intent.putExtra( "aspectY", 1 );
intent.putExtra( "scale", true );
//intent.putExtra( "", true ); // I seem to have lost the option to have the crop app auto rotate the image, any takers?
intent.putExtra( "return-data", true );
for ( ResolveInfo res : list )
{
final CropOption co = new CropOption();
co.TITLE = getPackageManager().getApplicationLabel( res.activityInfo.applicationInfo );
co.ICON = getPackageManager().getApplicationIcon( res.activityInfo.applicationInfo );
co.CROP_APP = new Intent( intent );
co.CROP_APP.setComponent( new ComponentName( res.activityInfo.packageName, res.activityInfo.name ) );
cropOptions.add( co );
}
// set up the chooser dialog
CropOptionAdapter adapter = new CropOptionAdapter( this, cropOptions );
AlertDialog.Builder builder = new AlertDialog.Builder( this );
builder.setTitle( R.string.choose_crop_title );
builder.setAdapter( adapter, new DialogInterface.OnClickListener() {
public void onClick( DialogInterface dialog, int item )
{
startActivityForResult( cropOptions.get( item ).CROP_APP, ACTIVITY_CROP );
}
} );
builder.setOnCancelListener( new DialogInterface.OnCancelListener() {
@Override
public void onCancel( DialogInterface dialog )
{
// we don't want to keep the capture around if we cancel the crop because we don't want it anymore
if ( _captureUri != null )
{
getContentResolver().delete( _captureUri, null, null );
_captureUri = null;
}
}
} );
AlertDialog alert = builder.create();
alert.show();
}
catch ( Exception e )
{
Log.e( TAG, "processing capture", e );
}
And there you have it... Hope that helps, I lost 2 days trying to figure it out...
I found a way by following the LogCat while i was cropping a contact Image. It called the Intent with following parameters:
cmp=com.android.gallery/com.android.camera.CropImage
So try to replace the com.android.camera
with com.android.gallery
. This worked for me:
Intent intent = new Intent("com.android.camera.action.CROP");
intent.setClassName("com.android.gallery", "com.android.camera.CropImage");
On some Android version, including the newest, com.android.gallery doesn't exist anymore. You need to use this then:
Intent intent = new Intent("com.android.camera.action.CROP");
intent.setClassName("com.google.android.gallery3d", "com.android.gallery3d.app.CropImage");