Невозможно найти активность com.android.camera.CropImage в Android
Я пытаюсь запустить образец PhotoStream по следующей ссылке
http://android-developers.blogspot.com/2008/09/android-photostream.html
Но когда я пытаюсь установить обои для изображения (класс ссылки ViewPhotoActivity.java), я получаю следующую ошибку
android.content.ActivityNotFoundException:
Невозможно найти явный класс активности {com.android.camera/com.android.camera.CropImage}; Вы объявили об этой активности в вашем AndroidManifest.xml?
и я думаю, что следующий код вызывает проблему
final Intent intent = new Intent("com.android.camera.action.CROP");
intent.setClassName("com.android.camera", "com.android.camera.CropImage");
intent.setData(Uri.fromFile(mFile));
intent.putExtra("outputX", width);
intent.putExtra("outputY", height);
intent.putExtra("aspectX", width);
intent.putExtra("aspectY", height);
intent.putExtra("scale", true);
intent.putExtra("noFaceDetection", true);
intent.putExtra("output", Uri.parse("file:/" + mFile.getAbsolutePath()));
startActivityForResult(intent, REQUEST_CROP_IMAGE);
Поскольку я пытался найти решение этой проблемы, но не получил никакого.
6 ответов
Я нашел способ, следуя LogCat, когда я обрезал изображение контакта. Вызывается Intent со следующими параметрами:
cmp=com.android.gallery/com.android.camera.CropImage
Так что попробуйте заменить com.android.camera
с com.android.gallery
, Это сработало для меня:
Intent intent = new Intent("com.android.camera.action.CROP");
intent.setClassName("com.android.gallery", "com.android.camera.CropImage");
На некоторых версиях Android, включая самую новую, com.android.gallery больше не существует. Вам нужно использовать это тогда:
Intent intent = new Intent("com.android.camera.action.CROP");
intent.setClassName("com.google.android.gallery3d", "com.android.gallery3d.app.CropImage");
На самом деле существует довольно много приложений, которые предлагают действие CROP в Android 2.x: стандартная Галерея или Обои Flikie, чтобы назвать пару. Почему не удается разрешить намерения, потому что Google изменил компоненты, которые предоставляют API. В Android 1.x это могло бы быть com.android.gallery, но, поскольку (я думаю) API9/Android 2.3.x, галерея по умолчанию предоставляется Cooliris, так что это что-то вроде com.cooliris.gallery и т. Д.
Правильный способ определения цели на любом телефоне - это (код, который я использую):
// 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;
}
}
Макет для элемента должен быть горизонтальным линейным макетом с IconView и TextView. Я пропущу это для краткости, теперь вы, скорее всего, знаете, как это сделать:-)
Теперь для части, где мы находим намерения и представляем их для выбора (это только соответствующая часть функции 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 );
}
И вот, у вас это есть... Надеюсь, это поможет, я потерял 2 дня, пытаясь понять это...
Альтернатива - позволить приложению сначала сохранить изображение и вручную обрезать его, то есть:
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();
}
Результат успеха приводит к:
@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;
А затем обработайте ваше обрезанное изображение.
Вы можете связать CropImage
активность с пакетом приложения, поэтому он не зависит от версии Android.
Вот проект: https://github.com/lvillani/android-cropimage
Деятельность CropImage, извлеченная из Gallery.apk (AOSP 4.4.4). Совместимо с Android API уровня 15 и выше.
Не забудьте добавить следующую строку в ваш AndroidManifest.xml
:
<!-- Declare the bundled CropImage Activity -->
<activity android:name="com.android.camera.CropImage"/>
Просто удалите:
intent.setClassName("com.android.camera", "com.android.camera.CropImage");
он спросит, из какого приложения вы хотите обрезать изображение.
Я помню, что читал, что это недокументированная функция и не существует ни в одном API. Теперь это не доступно в 2.x
Если в SDK нет константы для строки "com.android.camera.action.CROP", то это просто не является частью SDK, и в будущем она может сломаться.