2011-01-06 10 views
6

He integrado con éxito la búsqueda de país de mi aplicación en la función de búsqueda global y ahora estoy tratando de mostrar el indicador de cada país al lado de las sugerencias de búsqueda. La búsqueda dentro de mi aplicación funciona de esta manera, pero, por supuesto, tengo el control de la lista y su visión vinculante. Entonces sé que las banderas están todas allí y puedo usarlas en el resto de mi aplicación.¿Cómo obtengo un URI en una imagen en Mis activos que funcionará para la columna SearchManager.SUGGEST_COLUMN_ICON_1?

El problema surge cuando trato de suministrar un Uri a un archivo .gif en mis activos. De acuerdo con la documentación de búsqueda, el valor de la columna con la clave SearchManager.SUGGEST_COLUMN_ICON_1 debe ser un Uri para la imagen.

A continuación se muestra el código. En respuesta al método ContentProviderpublic Cursor query (Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder), estoy creando un MatrixCursor que mapea columnas de la base de datos de mi país a aquellas requeridas por el servicio de búsqueda. Los nombres de países aparecen bien y puedo seleccionarlos y responder correctamente en mi aplicación.

He intentado formar el URI de tres maneras diferentes:

//     String flagUri = "file:///android_asset/" + flagPath; 
//     String flagUri = "file:///assets/" + flagPath; 
        String flagUri = "android.resource://com.lesliesoftware.worldinfo.WorldInfoActivity/assets/" + flagPath; 
        columnValues.add (flagUri); 

todos ellos conducen a la misma cosa - mi icono de la aplicación junto a cada sugerencia que puedo recibir al usar un valor de cadena vacía.

¿Hay un Uri que funcione? ¿Cómo puedo obtener el icono de la bandera del país al lado de las sugerencias de búsqueda?

Gracias Ian

La fuente completo:

private Cursor search (String query, int limit) { 
    query = query.toLowerCase(); 
    String[] requestedColumns = new String[] { 
      BaseColumns._ID, 
      SearchManager.SUGGEST_COLUMN_TEXT_1, 
      SearchManager.SUGGEST_COLUMN_ICON_1, 
    }; 
    String[] queryColumns = new String[] { 
      WorldInfoDatabaseAdapter.KEY_ROWID, 
      WorldInfoDatabaseAdapter.KEY_COUNTRYNAME, 
      WorldInfoDatabaseAdapter.KEY_COUNTRYCODE 
    }; 

    return packageResults (query, requestedColumns, queryColumns, limit); 
} 


private Cursor packageResults (String query, String[] requestedColumns, String[] queryMappedColumns, int limit) { 
    if (requestedColumns.length != queryMappedColumns.length) 
     throw new IllegalArgumentException ("Internal error: requested columns do not map to query columns"); 

    MatrixCursor results = new MatrixCursor (requestedColumns); 

    // Query the country list returns columns: KEY_ROWID, KEY_COUNTRYNAME, KEY_COUNTRYCODE 
    Cursor dbResults = myDbHelper.getCountryList (query); 

    // Verify that the query columns are available 
    for (int index = 0; index < queryMappedColumns.length; index++) { 
     int col = dbResults.getColumnIndex (queryMappedColumns[index]); 
     if (col == -1) 
      throw new IllegalArgumentException ("Internal error: requested column '" + 
        queryMappedColumns[index] + "' was not returned from the database."); 
    } 

    // Loop over the database results building up the requested results 
    int rowCount = 0; 
    while (dbResults.moveToNext() && rowCount < limit) { 
     Vector<String> columnValues = new Vector<String>(); 
     for (int index = 0; index < requestedColumns.length; index++) { 
      if (requestedColumns[index].compareTo (SearchManager.SUGGEST_COLUMN_ICON_1) == 0) { 
       String flagPath = "flags/small/" + dbResults.getString (
         dbResults.getColumnIndexOrThrow (queryMappedColumns[index])) 
         + "-flag.gif"; 
//     String flagUri = "file:///android_asset/" + flagPath; 
//     String flagUri = "file:///assets/" + flagPath; 
       String flagUri = "android.resource://com.lesliesoftware.worldinfo.WorldInfoActivity/assets/" + flagPath; 
       columnValues.add (flagUri); 
      } else { 
       // Add the mapped query column values from the database 
       String colValue = dbResults.getString (dbResults.getColumnIndexOrThrow (queryMappedColumns[index])); 
       columnValues.add (colValue); 
      } 
     } 

     results.addRow (columnValues); 
     rowCount++; 
    } 

    return results; 
} 

EDIT: He probado otras variaciones, incluyendo mover las imágenes de los activos a la carpeta prima. Nada funcionó. Estos son los de Uri que probé:

flagUriStr = "android.resource://com.lesliesoftware.worldinfo/raw/flags/small/" + 
    countryCode + "-flag.gif"; 

flagUriStr = "android.resource://com.lesliesoftware.worldinfo/assets/flags/small/" + 
    countryCode + "-flag.gif"; 

flagUriStr = "android.resource://com.lesliesoftware.worldinfo/assets/flags/small/" + 
    countryCode + "-flag"; 

flagUriStr = "android.resource://com.lesliesoftware.worldinfo/raw/" + 
    countryCode + "-flag.gif"; 

flagUriStr = "android.resource://com.lesliesoftware.worldinfo/raw/" + 
    countryCode + "-flag"; 

El único URI que hizo el trabajo era si me movía una bandera de prueba en mi carpeta de dibujable:

flagUriStr = "android.resource://com.lesliesoftware.worldinfo/" + 
    R.drawable.small_ca_flag; 

Respuesta

7

Lamentablemente después de mucho buscar en torno he llegado a la conclusión de que no puede devolver un uri a un recurso de imagen en la función de búsqueda. Lo que hice en cambio fue mover las imágenes de mi bandera a los recursos (para que no abarroten los recursos de mi aplicación creé una biblioteca para las imágenes de las banderas) y usar las uri de recursos. Así, en el profesional tengo código que se parece a esto en el bucle que mapea los resultados de base de datos de los resultados de búsqueda:

  if (requestedColumns[index].compareTo (SearchManager.SUGGEST_COLUMN_ICON_1) == 0) { 
       // Translate the country code into a flag icon uri 
       String countryCode = dbResults.getString (
         dbResults.getColumnIndexOrThrow (queryMappedColumns[index])); 

       int flagImageID = FlagLookup.smallFlagResourceID (countryCode); 
       String flagUriStr = "android.resource://com.lesliesoftware.worldinfo/" + flagImageID; 
       columnValues.add (flagUriStr); 
      } 

y buscar el código que se parece a esto:

static public int smallFlagResourceID (String countryCode) { 
    if (countryCode == null || countryCode.length() == 0) 
     return R.drawable.flag_small_none; 

    if (countryCode.equalsIgnoreCase ("aa")) 
     return R.drawable.flag_small_aa; 
    else if (countryCode.equalsIgnoreCase ("ac")) 
     return R.drawable.flag_small_ac; 
    else if (countryCode.equalsIgnoreCase ("ae")) 
     return R.drawable.flag_small_ae; 
    ... 

sólo voy a tener para asegurarme de crear una prueba que verifique que todos los países que tienen indicadores devuelvan los resultados esperados.

+0

En realidad, se puede hacer. Ver a continuación la respuesta. :-) – vidstige

5

Primero crea un AssetProvider. Más adelante crearemos uris que serán manejados por esta clase.

public class AssetsProvider extends ContentProvider { 

    private AssetManager assetManager; 
    public static final Uri CONTENT_URI = 
      Uri.parse("content://com.example.assets"); 

    @Override 
    public int delete(Uri arg0, String arg1, String[] arg2) { return 0; } 

    @Override 
    public String getType(Uri uri) { return null; } 

    @Override 
    public Uri insert(Uri uri, ContentValues values) { return null; } 

    @Override 
    public boolean onCreate() { 
     assetManager = getContext().getAssets(); 
     return true; 
    } 

    @Override 
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { return null; } 

    @Override 
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { return 0; } 

    @Override 
    public AssetFileDescriptor openAssetFile(Uri uri, String mode) throws FileNotFoundException { 
     String path = uri.getPath().substring(1); 
     try { 
      AssetFileDescriptor afd = assetManager.openFd(path); 
      return afd; 
     } catch (IOException e) { 
      throw new FileNotFoundException("No asset found: " + uri, e); 
     } 
    } 
} 

Hay un montón de texto dentro. El método esencial es, por supuesto, el openAssetFile que justs traduce la ruta de acceso del uri en un AssetFileDescriptor.Con el fin de Android para poder pasar los URI a este proveedor, recuerde incluir esto en su archivo AndroidManifest.xml dentro de la aplicación de la etiqueta:

<provider 
     android:name=".AssetsProvider" 
     android:authorities="com.example.assets" /> 

Ahora, en su proveedor de búsqueda que puede crear un URI como esta :

content://com.example.assets/my_folder_inside_assets/myfile.png 
+1

¡Gracias, esto funcionó para mí! Hubo algunos inconvenientes (como si creo que CONTENT_URI * tiene * para estar allí? Estaba teniendo problemas cuando no era así) – phreakhead

+0

sí, el CONTENT_URI debe estar allí, será leído por Andoid y coincidirá con el 'android: atributo de las autoridades en el manifiesto. – vidstige

+0

¡Oye! ¡Gran respuesta! Tengo problemas debido al tamaño de la imagen del activo que se ha cargado. Entiendo que esto se debe al hecho de que las imágenes cargadas de la carpeta de activos no tienen la función de "escalado" en función de la densidad de la pantalla que tienen las imágenes cargadas desde la carpeta de recursos. ¿Alguna idea sobre cómo solucionar este problema? – acrespo

0

sólo quería añadir a la respuesta de vidstige: quería servir archivos que había descargado en mi directorio de caché temporal anterior, por lo que puede servir miniaturas de las imágenes externas a las sugerencias SearchView de direcciones URL en mi búsqueda ContentProvider. He utilizado esta función en lugar:

@Override 
public AssetFileDescriptor openAssetFile(Uri uri, String mode) throws FileNotFoundException { 
     String filename = uri.getLastPathSegment(); 

     try { 
      File file = new File(getContext().getCacheDir(), filename); 

      // image downloading has to be done in the search results provider, since it's not on the UI thread like this guy. 
      //downloadAndSaveFile("http://urdomain/urfile.png", filename); 

      AssetFileDescriptor afd = new AssetFileDescriptor(
         ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY | ParcelFileDescriptor.MODE_WORLD_READABLE), 
        0, AssetFileDescriptor.UNKNOWN_LENGTH); 

      return afd; 
     } catch (IOException e) { 
      throw new FileNotFoundException("No asset found: " + uri); 
     } 
    } 
1

yo era capaz de vincular las imágenes de dibujable en SearchRecentSuggestionsProvider usando siguiente URI,

"android.resource://your.package.here/drawable/image_name 
+1

los bienes y bienes no son lo mismo – vidstige

Cuestiones relacionadas