选择壁纸时使用壁纸区域高亮的意图

18

我想知道是否可以创建一个意图,使画廊裁剪器显示突出墙纸的功能。这个功能已经在Honeycomb中引入。要了解我正在寻找什么,请查看图片上的平板电脑(三个蓝色矩形)。

我查看了ICS画廊应用程序源代码,但是我找不到我要找的内容。

this

6个回答

8
我想知道是否可能创建一个Intent,使画廊裁剪器显示突出显示的壁纸。假设你希望你的应用程序在所有Android设备上表现正常,那么答案是否定的。剪裁活动和突出显示的剪裁视图都不是公共API的一部分,两者都是Gallery 3D应用程序内部的内容。换句话说,你可以花费所有时间来寻找一个Intent操作,让它神奇地为你工作,但事实是,一些设备简单地不支持它。例如,许多设备,如HTC Sense和Samsung Galaxy,具有自己的图库应用程序的自定义Android版本。由于这些画廊应用程序是特定于设计它们的公司的,因此这些设备不一定会有一个CropImage类供您启动。话虽如此,为了保证您的应用程序在所有设备上都能正常工作,您将不得不将裁剪代码直接合并到您的项目中。如果您以某种方式找到了使用Intent启动裁剪活动的方法,则应测试是否至少存在com.android.gallery3d软件包,并进行处理。我在下面提供了一个解决方法,它可能有助于你将Android代码整合到你的项目中。我目前没有一台运行Honeycomb / ICS的平板电脑,因此我无法具体说明如何在新版本的Android上使其正常工作,但我想它涉及类似的分析和从com.android.gallery3d包中复制和粘贴的一些东西。在Android 2.x上重用“裁剪活动”:我在我的Nexus One上测试了这个应用程序,在软“裁剪矩形”出现之前,我得到了以下logcat输出:
I/ActivityManager(   94): Starting: Intent { 
    act=android.intent.action.CHOOSER 
    cmp=android/com.android.internal.app.ChooserActivity (has extras) } from pid 558
I/ActivityManager(   94): Starting: Intent { 
    act=android.intent.action.ATTACH_DATA 
    dat=content://media/external/images/media/648 
    typ=image/jpeg 
    flg=0x3000001 
    cmp=com.google.android.gallery3d/com.cooliris.media.Photographs (has extras) } from pid 558
I/ActivityManager(   94): Starting: Intent { 
    dat=content://media/external/images/media/648 
    cmp=com.google.android.gallery3d/com.cooliris.media.CropImage (has extras) } from pid 558

所以根据我了解的情况,执行此操作时发生的事件顺序如下:
  1. You navigate to an image in the gallery and select "set as...". An ActivityChooser pops up and you select "Wallpaper".
  2. This selection fires an Intent with action ATTACH_DATA and component com.cooliris.media.Photographs, which is a class in the Android framework that serves as a "wallpaper picker" for the camera application; it just redirects to the standard pick action. Since we have given the Intent a URI that specifies the image to set as the wallpaper, this class will inevitably execute the following code (see the class's onResume method):

    Intent intent = new Intent();   
    intent.setClass(this, CropImage.class);
    intent.setData(imageToUse);
    formatIntent(intent);
    startActivityForResult(intent, CROP_DONE);
    
  3. This fires another Intent that starts the CropImage Activity... this is where you specify the cropped area using the soft-rectangle. When you specify the crop, the result is set to RESULT_OK with requestCode = CROP_DONE. The Photographs Activity switch-cases over these two constants and then sets the wallpaper accordingly (see the Photographs class's onActivityResult method).

很不幸,由于某些原因,Android团队决定从API 4(Android v1.6)开始从SDK中删除这些功能...所以如果您想要触发一个Intent来执行这些确切的事件序列,您需要在com.cooliris.media包中查找,并将相关类复制粘贴到您的项目中。根据我的过去经验,这样做往往比它值得的麻烦多(除非它是为了执行相对简单的操作),但绝对是可能的。
这里有一篇不错的教程,介绍了如何简化这个过程...它要求您将12个Java类复制粘贴到您的项目中,而不是整个com.cooliris.media包。这些类在一起应该足以正确地启动CropImage活动,但您必须手动设置壁纸以响应CropImage活动的结果。
还要注意,提供的示例代码假定您想在相机拍摄照片后立即裁剪。为了例如使用来自图库的预选图像启动CropImage活动,您需要调用:
Intent i = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(i, ACTIVITY_SELECT_IMAGE);

onActivityResult中,如果requestCode == ACTIVITY_SELECT_IMAGE并且resultCode == RESULT_OK,请使用onActivityResult的第三个参数中给定的Uri数据启动CropImage Activity(有关如何启动Activity的示例,请参见示例代码)。
如果你还有疑问,请让我知道,并留下评论让我澄清任何问题。

2
Alex,"好教程"的链接已经失效了。你能更新一下吗?谢谢。 - kdroider

2

I this will help:

public class CropSelectedImageActivity extends Activity {

    @Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
            photoPickerIntent.setType("image/*");
            startActivityForResult(photoPickerIntent, 1);
}

    public void onActivityResult(int requestCode, int resultCode, Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
            if (resultCode == RESULT_OK) {
                    final Bundle extras = data.getExtras();
                    Uri photoUri = data.getData();
                    if (photoUri != null) {
                            Intent intent = new Intent("com.android.camera.action.CROP");
                    //intent.setClassName("com.android.camera", "com.android.camera.CropImage");

                    intent.setData(photoUri);
                    intent.putExtra("outputX", 96);
                    intent.putExtra("outputY", 96);
                    intent.putExtra("aspectX", 1);
                    intent.putExtra("aspectY", 1);
                    intent.putExtra("scale", true);
                    intent.putExtra("return-data", true);            
                    startActivityForResult(intent, 1);
                    }
            }
    }
}

取自:ImageCropper
(说明:此处为原文,无需翻译)

1

我没有尝试过这个,但如果你看一下这里

         Bundle newExtras = new Bundle();
         // maybe that here - for more options see your source code link
         newExtras.putString("circleCrop", "true");
         Intent cropIntent = new Intent();
         // Uri would be something from MediaStore.Images.Media.EXTERNAL_CONTENT_URI
         cropIntent.setData(img.fullSizeImageUri());
         // edit: it's inside com.android.gallery in case that is even installed.
         // should work if you replace that with setClassName("com.android.gallery", "com.android.camera.CropImage")
         cropIntent.setClass(this, CropImage.class);
         cropIntent.putExtras(newExtras);
         startActivityForResult(cropIntent, CROP_MSG);

如果你想尝试一下,这可能会对你有所帮助。

也许可以通过选择意图的方式实现:

Intent i = new Intent(Intent.ACTION_PICK);
i.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
startActivity(i);

当使用cropIntent.setClassName("com.android.camera", "com.android.camera.CropImage");时,我遇到了ActivityNotFoundException异常。此外,我正在寻找一个普通图像选择意图(Intent.ACTION_PICK)的适应,尽管我现在意识到问题在这方面并不清楚。 - Thomas
你找到的代码来自“相册”应用程序。还有一个“相册2”和Google的闭源版本。所以也许我们看错了完全错误的源代码。此外,据我所见,它应该是cropIntent.setClassName("com.android.gallery", "com.android.camera.CropImage")。对于Intent.ACTION_PICK,请参见更新的答案。未经测试,但可能有效。 - zapl

1

有一个很好的库,基于ICS的裁剪屏幕(来自相册应用程序),在这里

您可以根据需要修改它,以选择要裁剪的部分。

该代码基于Android的Gallery应用程序(链接在这里),位于“/com/android/camera/gallery”,而最重要的类是“/com/android/camera/”中的“CropImage”。即使缺少库,它也适用于所有人(Google的代码始终可用):

git clone https://android.googlesource.com/platform/packages/apps/Gallery3D/

即使这不可用,我相信还会有其他的解决方案。

与其他解决方案相比的优点:

  • 独立性
  • 可定制性
  • 不会因ROM中的更改而崩溃。其他解决方案假定存在特定的类和应用程序。
  • 开源。
  • 一个真正的实现,而不是启动到另一个应用程序的意图。
  • 其他解决方案高度不推荐,仅是因为使用非官方意图,如此处所述。这是由一个非常知名的StackOverflow用户“CommonsWare”编写的,他是一个非常值得尊敬的用户,在很多Android相关主题上都可以依靠他。

再次强调,裁剪图像最推荐的方法仍然是使用第三方库。不要使用意图的解决方法。


1
虽然这个链接可能回答了问题,但最好在此处包含答案的基本部分并提供参考链接。如果链接页面更改,仅有链接的答案可能会失效。 - Christian Garbin
@chr 有时候,由于代码太庞大和复杂,并且除了Java之外还有其他类型的文件,因此在此处发布它是不可能的,最好提供一个真实的Github链接。该代码是基于Android代码的开源代码。这里的其他解决方案虽然很短,但是却很危险,因为它们对设备上现有应用程序做出了假设。如果设备上没有它们,就无法进行裁剪。这些解决方案实际上是在可能不存在的应用程序上实现的。他们甚至没有检查它是否存在,因此应用程序可能会崩溃。 - android developer
@chr 所以,在可能会崩溃且完全不可定制的东西和基于谷歌代码的开源且可用的东西之间,我认为我的解决方案更好。也许如果 StackOverflow 允许我上传完整的项目,我会这样做,但我不能。 - android developer

1

只要这样做!

Intent intent = new Intent(Intent.ACTION_ATTACH_DATA).setDataAndType(contentUri,  "image/jpeg")
    .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
    .putExtra("mimeType", "image/jpeg");
startActivity(Intent.createChooser(intent, getString(R.string.set_as)));

"image/jpeg" 是图片的 MIME 类型,contentUri 是该图片的 URI。"

0

试试这个

    // Set Home wallpaper the image
public void setHomeWallpaper () {
                BitmapDrawable bitmapDrawable = ((BitmapDrawable) imageView.getDrawable());
                Bitmap bitmap = bitmapDrawable.getBitmap();
                String bitmapPath = Images.Media.insertImage(getContentResolver(), bitmap, "", null);
                Uri bitmapUri = Uri.parse(bitmapPath);
                Intent intent = new Intent(Intent.ACTION_ATTACH_DATA).setDataAndType(bitmapUri,  "image/jpeg")
                        .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
                        .putExtra("mimeType", "image/jpeg");
                startActivity(Intent.createChooser(intent, getString(R.string.background)));
                Toast.makeText(PicassoDisplayImageAdapter.this, "قم بإختيار التطبيق المناسب لتعيين الصورة", Toast.LENGTH_SHORT).show();
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接