【问题标题】:Choosing background for Live Wallpaper选择动态壁纸的背景
【发布时间】:2010-09-09 18:11:55
【问题描述】:

我正在编写一个动态壁纸,可以在背景上创建效果。我希望用户能够从任何系统壁纸和相机照片中选择背景。我希望用户能够按下“设置”菜单中的按钮,显示选项列表,就像从主屏幕设置壁纸一样,减去“动态壁纸”选项。一旦用户导航选择并选择了实际图像,我会将其加载到我的画布中。

我该怎么做?

我在任何地方都找不到用于获取壁纸列表的 API。

我已经能够提出使用 Intents 的壁纸提供商列表。然后我得到一个动态壁纸供应商的列表也使用 Intents 并将它们从我的第一个列表中删除。这给了我一个不在线的壁纸供应商列表。

现在呢?还有其他我想念的方法吗?

请帮忙。

【问题讨论】:

    标签: android live-wallpaper


    【解决方案1】:

    我通过将首选项放入设置 xml 中来做到这一点(我的是 flash_setting.xml);

    <Preference
        android:key="image_custom"
        android:title="Choose Background"
        android:summary="Select a Custom Image"
         />
    

    我创建了一个自定义类来获取 OnPreferenceClick 侦听器并监视用户单击首选项(这称为 mySettings.java)(请注意 getRealPathFromURI 例程不是我的,而是在此处的其他地方找到的);


    您的课程应该从扩展 PreferenceActivity 并实现 Sharedpreference 更改监听器开始

    public class flashSettings extends PreferenceActivityimplements SharedPreferences.OnSharedPreferenceChangeListener {    
    

    链接到偏好名称并注册监听器

    @Override
    protected void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        getPreferenceManager().setSharedPreferencesName(
                fingerflashpro.SHARED_PREFS_NAME);
        addPreferencesFromResource(R.xml.flash_settings);      getPreferenceManager().getSharedPreferences().registerOnSharedPreferenceChangeListener(
                this);
    

    接下来,我们将设置 on preference 侦听器以侦听“image_custom”。单击它时,我们将启动一个新的意图来显示照片选择器。我们从 StartActivityForResult 开始,这样我们就可以从意图中获取图像的 URI。

    getPreferenceManager().findPreference("image_custom").setOnPreferenceClickListener(new OnPreferenceClickListener()
    {
        @Override
        public boolean onPreferenceClick(Preference preference)
        {
            Display display = getWindowManager().getDefaultDisplay(); 
            int width = display.getWidth();
            int height = display.getHeight();
            Toast.makeText(getBaseContext(), "Select Image - " + (width) + " x " + height , Toast.LENGTH_LONG).show(); 
            Intent photoPickerIntent = new Intent(Intent.ACTION_PICK); 
            photoPickerIntent.setType("image/*");
            startActivityForResult(photoPickerIntent, 1);
            return true;
        }
    });}
    

    接下来我们等待 Activity 返回结果并将 URI 解析为真实路径。

    @Override 
    public void onActivityResult(int requestCode, int resultCode, Intent data) { 
    super.onActivityResult(requestCode, resultCode, data); 
    if (requestCode == 1) {
    if (resultCode == Activity.RESULT_OK) { 
      Uri selectedImage = data.getData();   
      String RealPath;
      SharedPreferences customSharedPreference = getSharedPreferences(fingerflashpro.SHARED_PREFS_NAME, Context.MODE_PRIVATE); 
      SharedPreferences.Editor editor = customSharedPreference.edit ();
      RealPath = getRealPathFromURI (selectedImage);
      editor.putString("image_custom", RealPath); 
      editor.commit(); 
    }}
    

    在此站点上找到了以下代码(由 PercyPercy 在this thread 上),我只是为了完整性而将其包括在内。但是,它确实可以完美运行。

    public String getRealPathFromURI(Uri contentUri) {          
    String [] proj={MediaColumns.DATA};  
    Cursor cursor = managedQuery( contentUri,  
            proj, // Which columns to return  
            null,       // WHERE clause; which rows to return (all rows)  
            null,       // WHERE clause selection arguments (none)  
            null); // Order-by clause (ascending by name)  
    int column_index = cursor.getColumnIndexOrThrow(MediaColumns.DATA);  
    cursor.moveToFirst();  
    return cursor.getString(column_index);}
    

    确保我们实现了所需的覆盖;

    @Override
    protected void onResume() {
        super.onResume();
    }
    
    @Override
    protected void onDestroy() {
        getPreferenceManager().getSharedPreferences().
           unregisterOnSharedPreferenceChangeListener(this);
        super.onDestroy();
    }
    
    @Override
    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
            String key) {
    }}
    

    然后在您的主要壁纸服务活动中,您可以从您的共享偏好中提取图像的路径。

    @Override
        public void onSharedPreferenceChanged(SharedPreferences prefs,
                String key) {
    
            imageBg = prefs.getString("image_custom", "Bad Image");
                getBackground();}
    

    这是一个相当粗略的加载图像的例程。我试图设置一些错误捕获,以防文件被删除、重命名或 SD 卡被挂载(因此你丢失了你的图像)。我还尝试对设备方向进行一些粗略的检查。我相信你可以做得更好。

    还有一些 Samplesize 检查,因此您不会超出 VM 预算。这是这段代码中防止强制关闭最重要的部分,绝对应该包含在内。

    当手机的方向发生变化时,我也会调用这个例程,以便每次调整背景大小。

    void getBackground() { 
            if (this.cvwidth == 0 || this.cvheight == 0 || this.visibleWidth == 0) {
                   this.cvwidth = 480;
                   this.cvheight = 854;
                   this.visibleWidth = 480;}
            if(new File(imageBg).exists()) {
                    int SampleSize = 1;
                 do {
                     BitmapFactory.Options options = new BitmapFactory.Options();
                     options.inJustDecodeBounds = true;
                     bg = BitmapFactory.decodeFile(imageBg, options);
                    SampleSize = (int) (Math.ceil(options.outWidth/(this.visibleWidth * 2))*2);
                    options.inJustDecodeBounds = false;
                     try {options.inSampleSize = SampleSize;
                         bg = BitmapFactory.decodeFile(imageBg, options);}
                        catch (OutOfMemoryError e) {
                            SampleSize = SampleSize * 2;
                            }
                    } while (bg == null);
    
               bg = Bitmap.createScaledBitmap(bg, this.cvwidth/2, this.cvheight, true);}
            else {bg = BitmapFactory.decodeResource(getResources(), R.drawable.bg);
                bg = Bitmap.createScaledBitmap(bg, this.cvwidth/2, this.cvheight, true);}
            LoadText = "";
        } 
    

    我希望这会有所帮助。我花了很长时间才想出所有这些,我知道我仍然可以改进一些领域,但至少它应该能让你继续前进。

    如果有人对改进此代码有任何建议,那么我会全力以赴。

    【讨论】:

    • 这是否提供了用户从主屏幕看到的相同壁纸列表?这就是我想要的。用户需要能够从系统壁纸和其他应用提供的壁纸中进行选择,而不需要动态壁纸。
    • 这让您可以浏览 SD 卡上的每张图片。如果您下载 wabbittdevs 的免费 Droid X 动态壁纸,这正是您将体验到的。这就是上面代码的来源。
    • 我下载并检查了它。那不是我想要的。在设备的主屏幕上,按“菜单”并选择“壁纸”。这是我希望用户拥有的列表,减去动态壁纸。在我的设备上,我可以获得动态壁纸、照片和 HTC 壁纸。模拟器为您提供动态壁纸、照片和壁纸,以及 Home 示例提供的“壁纸”条目。这些是满足意图 ACTION_SET_WALLPAPER 的活动。看来我想要的 API 不能轻易做到。
    • 啊。我明白你现在想要什么。我以前从来没有解决过这样做的需要,很抱歉,帮不上忙。
    • 我需要这样做,我必须说你的回答很棒
    【解决方案2】:

    不,这几乎是最好的方法。任何响应 android.intent.action.SET_WALLPAPER 的东西都是一种或另一种形式的壁纸提供者。问题是,给他们这份清单会让你失去控制权。基本上让他们从其他提供商那里挑选一些东西会取消您的动态壁纸。您可能可以通过一些创造性的清单设置和/或一些“startActivityForResult”类型调用来解决这个问题。

    在他们选择了一些东西之后,尽管在你的 WallpaperService.Engine 中这是一个简单的事情:

    @Override
    public void onSurfaceChanged( SurfaceHolder holder, int format, int width, int height )
    {
        super.onSurfaceChanged( holder, format, width, height );
        if( isVisible() )
        {
        mSurfaceHolder = holder;
        final Drawable drawable = WallpaperManager.getInstance( getBaseContext() ).getFastDrawable();
        mSurfaceHolder.setFormat( RenderThread.pixFormat );
        Canvas c = mSurfaceHolder.lockCanvas();
        if( c != null )
            {
                drawable.draw( c );
                mSurfaceHolder.unlockCanvasAndPost( c );
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多