选择动态壁纸的背景

发布于 2024-09-18 01:58:24 字数 314 浏览 3 评论 0原文

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

我该怎么做?

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

我已经能够使用意图列出壁纸提供商的列表。然后,我获得也使用意图的动态壁纸提供商列表,并将其从我的第一个列表中删除。它为我提供了非实时壁纸提供商的列表。

现在怎么办?还有其他我缺少的方法可以做到这一点吗?

请帮忙。

I'm writing a live wallpaper that creates an effect over a background. I want the user to be able to choose the background from any of the system wallpapers and camera photos. What I would like is for the user to be able to press a button in the Settings menu, have the list of options show up just like setting the wallpaper from the home screen, minus the Live Wallpapers options. Once the user navigates the choices and picks an actually image I would load it to my canvas.

How do I do this?

I can't find an API anywhere for getting a list of wallpapers.

I've been able to come up with a list of wallpaper providers using Intents. I then get a list of live wallpaper providers also using Intents and remove those from my first list. The gives me a list of wallpaper providers that are not live.

Now what? Are there other ways to do this that I'm missing?

Please help.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

2024-09-25 01:58:24

我通过将首选项放入设置 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);

接下来,我们将设置首选项监听器来监听“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 在 此线程),我只是为了完整性才将其包括在内。然而,它确实工作得很好。

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 卡被安装(因此您会丢失图像)。我还尝试对设备方向进行一些粗略检查。我确信你可以做得更好。

还有一些样本大小检查,这样您就不会超出虚拟机预算。这是此代码中防止强制关闭的最重要部分,绝对应该包含在内。

当手机方向改变时,我也会调用此例程,以便每次调整背景大小。

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 = "";
    } 

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

如果有人有关于改进此代码的建议,那么我会洗耳恭听。

I do this by putting a preference into the Settings xml as this (mine is flash_setting.xml);

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

I created a custom class to take the get the OnPreferenceClick Listener and watch for the user clicking the preference as so (this is call mySettings.java) (please note that the getRealPathFromURI routine isn't mine and was found elsewhere on here);


Your class should start by extending the PreferenceActivity and implementing the Sharedpreference change listener

public class flashSettings extends PreferenceActivityimplements SharedPreferences.OnSharedPreferenceChangeListener {    

Link to the preference name and register the listener

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

Next we will set the on preference listener to listen for 'image_custom'. When it is clicked we will start a new intent to display the photo picker. We start with a StartActivityForResult so we can get the URI of the image back from the intent.

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;
    }
});}

Next we wait for the activity to return the result and we parse the URI to a real path.

@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(); 
}}

The following piece of code was found on this site (by PercyPercy on this thread)and I'm only including it for completeness. It does however, work perfectly.

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);}

Make sure we implement the required Overrides;

@Override
protected void onResume() {
    super.onResume();
}

@Override
protected void onDestroy() {
    getPreferenceManager().getSharedPreferences().
       unregisterOnSharedPreferenceChangeListener(this);
    super.onDestroy();
}

@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
        String key) {
}}

Then in your main wallpaper service activity you can extract the Path of the image from your shared preferences.

@Override
    public void onSharedPreferenceChanged(SharedPreferences prefs,
            String key) {

        imageBg = prefs.getString("image_custom", "Bad Image");
            getBackground();}

Here is a fairly crude routine to load the image. I've attempted to put in some error trapping just in case the file is deleted, renamed or the SD card gets mounted (hence you lose your image). I've also attempted to put in some crude checks for the device orientation. I'm sure you can do better.

There also some Samplesize checking so you don't exceed the VM budget. This is the most important part of this code to prevent force closes and should definitely be included.

I also call this routine when the orientation of the phone is changed so that the background gets resized each time.

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 = "";
    } 

I hope this helps. It took me an absolute age to come up with all of this and I know there are still some areas I can refine but at least it should get you going.

If anyone has suggestions on making this code better then I'm all ears.

洋洋洒洒 2024-09-25 01:58:24

不,这几乎是最好的方法。任何响应 android.intent.action.SET_WALLPAPER 的内容都将是一种或另一种形式的壁纸提供程序。问题是,向他们提供该列表将使您失去控制权。本质上,让他们从其他提供商那里选择一些东西会取消您的动态壁纸的设置。您可以通过一些创意清单设置和/或一些“startActivityForResult”类型调用来解决这个问题。

在他们选择某些内容后,在您的壁纸服务引擎中,这是一个简单的事情,如下所示:

@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 );
        }
    }
}

Nope, that's pretty much the best way to go about it. Anything that responds to android.intent.action.SET_WALLPAPER would be a wallpaper provider of one form or another. The problem is that giving them that list will take your control out of the equation. Essentially having them pick something from another provider will unset your Live Wallpaper. You could probably get around this with with some creative Manifest settings and or some "startActivityForResult" type calls.

After they choose something though it's a simple matter of something like this in your 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 );
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文