选择动态壁纸的背景

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

我该怎么做呢?

我无法在任何地方findAPI来获取壁纸列表。

我已经能够使用Intents提出壁纸提供商列表。 然后,我获得了一个使用Intents的动态壁纸提供商列表,并从我的第一个列表中删除它们。 给我一个不活的壁纸提供商列表。

怎么办? 还有其他方法可以做到这一点,我错过了吗?

请帮忙。

我通过将一个首选项放入Settings xml来实现这一点(我的是flash_setting.xml);

 

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


您的类应该首先扩展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首选项侦听器以侦听“image_custom”。 单击它时,我们将启动一个新的意图来显示照片选择器。 我们从StartActivityForResult开始,这样我们就可以从intent中获取图像的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; } });} 

接下来,我们等待活动返回结果,并将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(); }} 

在这个网站上find了以下代码(PercyPercy在这个post上 ),我只是为了完整性而包含它。 然而,它确实完美。

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

我希望这有帮助。 我花了一个绝对的年龄来提出这一切,我知道还有一些方面我可以改进,但至少它应该让你去。

如果有人有关于使这些代码更好的建议,那么我全都听见了。

不,这几乎是最好的方式。 任何响应android.intent.action.SET_WALLPAPER的东西都是某种forms的壁纸提供者。 问题是,给他们这个列表将使你的控制不在等式中。 基本上让他们从其他提供商那里挑选东西将取消你的动态壁纸。 您可以通过一些创造性的Manifest设置和/或一些“startActivityForResult”types调用来解决这个问题。

在他们选择了一些东西之后,虽然在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 ); } } }