2010-09-09 16 views
5

Estoy escribiendo un fondo de pantalla en vivo que crea un efecto sobre un fondo. Quiero que el usuario pueda elegir el fondo de cualquiera de los fondos de pantalla del sistema y las fotos de la cámara. Lo que me gustaría es que el usuario pueda presionar un botón en el menú de Configuración, tener la lista de opciones que se muestran como si se configurara el fondo de pantalla desde la pantalla de inicio, menos las opciones de Fondos de pantalla en vivo. Una vez que el usuario navega por las opciones y elige una imagen en realidad, la cargaría en mi lienzo.Elección de fondo para Live Wallpaper

¿Cómo puedo hacer esto?

No puedo encontrar una API en ninguna parte para obtener una lista de fondos de pantalla.

He podido encontrar una lista de proveedores de fondos de pantalla que usan Intents. Luego obtengo una lista de proveedores de fondos de pantalla en vivo que también usan Intents y los elimino de mi primera lista. El me da una lista de proveedores de fondo de pantalla que no están en vivo.

¿Ahora qué? ¿Hay otras maneras de hacer esto que me estoy perdiendo?

Por favor ayuda.

Respuesta

25

Hago esto poniendo una preferencia en el xml de Configuración como este (el mío es flash_setting.xml);

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

he creado una clase personalizada para tomar el OnPreferenceClick obtener el oyente y el reloj para el usuario haga clic en la preferencia de modo que (esto es mySettings.java llamada) (tenga en cuenta que la rutina getRealPathFromURI no es la mía y fue encontrado en otro lugar aquí);


Su clase debe comenzar mediante la extensión de la PreferenceActivity y la implementación del cambio oyente Sharedpreference

public class flashSettings extends PreferenceActivityimplements SharedPreferences.OnSharedPreferenceChangeListener {  

Enlace al nombre de preferencia y registrar el detector

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

A continuación vamos a configurar el sobre escucha de preferencias para escuchar 'image_custom'. Cuando se haga clic en él, comenzaremos una nueva intención para mostrar el selector de fotografías. Comenzamos con un StartActivityForResult para que podamos recuperar el URI de la imagen.

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

A continuación, esperamos que la actividad devuelva el resultado y analizamos el URI en una ruta real.

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

El siguiente fragmento de código se ha encontrado en este sitio (por PercyPercy en this thread) y yo sólo estoy incluyendo que esté completa. Sin embargo, funciona a la perfección.

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

Asegúrate de que implementamos las modificaciones necesarias;

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

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

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

Luego, en su actividad de servicios de fondo Puede extraer la ruta de la imagen de sus preferencias compartidas.

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

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

Aquí hay una rutina bastante tosca para cargar la imagen.Intenté colocar algún error de captura solo en caso de que se elimine el archivo, renombre o se monte la tarjeta SD (por lo tanto, perderá su imagen). También intenté realizar algunos controles crudos de la orientación del dispositivo. Estoy seguro de que puedes hacerlo mejor.

También hay algunas comprobaciones Samplesize para que no exceda el presupuesto de VM. Esta es la parte más importante de este código para evitar el cierre de la fuerza y ​​definitivamente debe incluirse.

También llamo a esto rutina cuando se cambia la orientación del teléfono para que el fondo cambie de tamaño cada vez.

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

Espero que esto ayude. Me tomó la edad absoluta para llegar a todo esto y sé que todavía hay algunas áreas que puedo refinar, pero al menos debería ayudarte a avanzar.

Si alguien tiene sugerencias para mejorar este código, entonces soy todo oídos.

+0

esto proporciona la misma lista de fondos de pantalla que el usuario ve en la pantalla principal? Eso es lo que quiero. El usuario debe poder elegir entre fondos de pantalla del sistema y fondos de pantalla proporcionados por otras aplicaciones, sin los fondos de pantalla en vivo. – DarthNoodles

+0

Esto le permite navegar por cada imagen en su tarjeta SD. Si descarga el Droid X Livewallpaper gratis de wabbittdevs, esto es exactamente lo que experimentará. Ahí es donde se toma el código de arriba. – Dean

+0

Lo descargué y lo revisé. Eso no es lo que quiero. En la pantalla de inicio de su dispositivo, presione 'menú' y seleccione 'fondo de pantalla'. Esta es la lista que quiero que tenga el usuario, menos los Live Wallpapers. En mi dispositivo tengo Live Wallpaper, Fotos y HTC Wallpapers. El emulador te brinda Live Wallpaper, Fotos y Fondos de pantalla, además de una entrada de "Fondo de pantalla" proporcionada por la muestra de Inicio. Estas son las actividades que satisfacen la intención ACTION_SET_WALLPAPER. Parece que lo que deseo no se puede hacer fácilmente con la API tal como está. – DarthNoodles

0

No, esa es la mejor manera de hacerlo. Cualquier cosa que responda a android.intent.action.SET_WALLPAPER sería un proveedor de fondo de pantalla de una forma u otra. El problema es que darles esa lista eliminará su control de la ecuación. Esencialmente hacer que escojan algo de otro proveedor desarmará su Live Wallpaper. Probablemente pueda solucionar esto con algunas configuraciones de Manifiesto creativo y/o algunas llamadas de tipo "startActivityForResult".

Después de que elijan algo pesar de que es una simple cuestión de algo como esto en su 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); 
     } 
    } 
} 
Cuestiones relacionadas