sandwich cream android group-by android-contentprovider android-contacts

android 4.0 ice cream sandwich download tablet



Agrupar por en ContentResolver en Ice Cream Sandwich (2)

Estoy haciendo una consulta en el proveedor de contenido de contactos de Android. Necesito una cláusula por grupo. En Gingerbread and Honeycomb, hago algo como esto para buscar números de teléfono y correos electrónicos al mismo tiempo:

(La cláusula WHERE real es mucho más complicada ya que incluye verificaciones de tipos. Esto es una simplificación, pero produce el mismo resultado)

String request = Phone.NUMBER + " LIKE ? OR " + Email.DATA + " LIKE ?"; String[] params = new String["%test%", "%test%"]; Cursor cursor = getContentResolver().query( Data.CONTENT_URI, new String[] { Data._ID, Data.RAW_CONTACT_ID }, request + ") GROUP BY (" + Data.RAW_CONTACT_ID, params, "lower(" + Data.DISPLAY_NAME + ") ASC");

La inyección de '')'' finaliza la cláusula WHERE y permite la inserción de una cláusula GROUP BY.

Sin embargo, en Ice Cream Sandwich, parece que ContentProvider detecta esto y agrega el número correcto de paréntesis para evitar mi inyección. ¿Alguna otra forma de hacer esto en una sola consulta de cursor?

Editar

Actualmente, he eliminado GROUP BY y he añadido un MatrixCursor para limitar el impacto, pero prefiero tener un cursor real:

MatrixCursor result = new MatrixCursor(new String[] { Data._ID, Data.RAW_CONTACT_ID }); Set<Long> seen = new HashSet<Long>(); while (cursor.moveToNext()) { long raw = cursor.getLong(1); if (!seen.contains(raw)) { seen.add(raw); result.addRow(new Object[] {cursor.getLong(0), raw}); } }


En primer lugar, disculpe mi pobre inglés! Soy nuevo en Java / Android, comencé con 4.2.1 y lucho con eso también casi 2 días, luego empiezo a leer algunos detalles más sobre SQLiteQueryBuilder .

tiene:

public Cursor query (SQLiteDatabase db, String[] projectionIn, String selection, String[] selectionArgs, String groupBy, String having, String sortOrder)

La "función" de consulta del proveedor de contenido solo le proporciona:

query(Uri uri, String[] projection, String selection,String[] selectionArgs, String sortOrder)

Aquí puedes hacer trucos, te enviaré mi código:

@Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder(); final SQLiteDatabase db = mOpenHelper.getReadableDatabase(); /* a String is a Object, so it can be null!*/ String groupBy = null; String having = null; switch (sUriMatcher.match(uri)) { ... ... ... case EPISODES_NEXT: groupBy = "ShowID"; queryBuilder.setTables(EpisodenTable.TableName); break; default: throw new IllegalArgumentException("Unknown URI " + uri); } Cursor c = queryBuilder.query(db, projection, selection, selectionArgs, groupBy, having, sortOrder); c.setNotificationUri(getContext().getContentResolver(), uri); return c; }

¡eso es!

Aquí el código que utilizo para ejecutar:

Cursor showsc = getContext().getContentResolver().query( WhatsOnTVProvider.CONTENT_EPISODES_NEXT_URI, EpisodenTable.allColums_inclCount, String.valueOf(Calendar.getInstance().getTimeInMillis() / 1000) + " < date", null, null);


Podría crear un Uri personalizado de modo que cuando su UriMatcher en su ContentProvider obtenga, pueda insertar su grupo por cláusula y luego ejecutar el sql sin procesar directamente en la base de datos.