Añadir filas al cursor manualmente

Tengo una serie de números de teléfono y quiero obtener los nombres de contacto correspondientes de la base de datos de contactos.

En la matriz de números de teléfono, también tengo algunos números que no se guardan antes en la base de datos de contactos. Por ejemplo;

  • 3333333 -> Tim
  • 5555555 -> Jim
  • 1111111 -> desconocido

Tengo la matriz que contiene los números de teléfono mostrados arriba, a saber, phoneArr .

int size=phoneArr.size(); if(size>0){ Cursor[] cursors=new Cursor[size]; for(int i=0;i<size;i++){ Uri contactUri1 = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneArr.get(i))); cursors[i] = getContentResolver().query(contactUri1, PEOPLE_PROJECTION, null, null, " _id asc limit 1"); } Cursor phones=new MergeCursor(cursors); 

Phones.getCount () devuelve 2 en el escenario anterior. Cuando el número de teléfono no aparece en la lista de contactos el cursor se vuelve vacío y de alguna manera cuando los fusiono no aporta nada en absoluto. Lo que quiero es tener un cursor como sigue

Cursor teléfonos -> {Tim, Jim, 1111111}

Creo que puedo hacer esto agregando la fila manualmente como sigue:

 Uri contactUri1 = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneArr.get(i))); cursors[i] = getContentResolver().query(contactUri1, PEOPLE_PROJECTION, null, null, " _id asc limit 1"); if(cursors[i].getCount()==0) // add the phone number manually to the cursor 

¿Cómo puedo conseguir esto?

Aquí está PEOPLE_PROJECTION

 private static final String[] PEOPLE_PROJECTION = new String[] { ContactsContract.PhoneLookup._ID, ContactsContract.PhoneLookup.DISPLAY_NAME, ContactsContract.PhoneLookup.NUMBER }; 

La manera más fácil de agregar filas en un cursor es usar un MatrixCursor y un MergeCursor . Esas dos clases son del SDK y aquí para resolver ese tipo de problemas.

Básicamente lo que haces es:

  1. Coloque las filas que desea agregar en un MatrixCusror
  2. Combinar el cursor y el cursor matrixCursor con un MergeCursor

Algo como:

 // Create a MatrixCursor filled with the rows you want to add. MatrixCursor matrixCursor = new MatrixCursor(new String[] { colName1, colName2 }); matrixCursor.addRow(new Object[] { value1, value2 }); // Merge your existing cursor with the matrixCursor you created. MergeCursor mergeCursor = new MergeCursor(new Cursor[] { matrixCursor, cursor }); // Use your the mergeCursor as you would use your cursor. 

Yo uso una solución que hace el truco para todas mis diferentes necesidades, y que es más simple que la implementación de Cursor.
Aquí hay un ejemplo en el que tengo que agregar filas adicionales de "lista de reproducción" a un Cursor, recuperado de la Mediastore. Añado filas en los primeros índices del cursor original:

 public class CursorWithExtraPlaylists extends CursorWrapper { public static final int ID_COLUMN_INDEX = 0; public static final int NAME_COLUMN_INDEX = 1; private int mPos = -1; private Context mContext; private Playlist[] extras; public CursorWithExtraPlaylists(Cursor cursor, Context context, Playlist[] extras) { super(cursor); mContext = context; this.extras = extras; } @Override public int getCount() { return super.getCount() + extras.length; } @Override public int getPosition() { return mPos; } @Override public boolean moveToFirst() { return moveToPosition(0); } @Override public boolean moveToLast() { return moveToPosition(getCount() - extras.length); } @Override public boolean move(int offset) { return moveToPosition(mPos + offset); } @Override public boolean moveToPosition(int position) { // Make sure position isn't past the end of the cursor final int count = getCount(); if (position >= count) { mPos = count; return false; } // Make sure position isn't before the beginning of the cursor if (position < 0) { mPos = -1; return false; } // Check for no-op moves, and skip the rest of the work for them if (position == mPos) { return true; } mPos = position; if (mPos > 0) { // ok, that concerns super cursor return super.moveToPosition(mPos - 1); } return true; } @Override public boolean moveToNext() { return moveToPosition(mPos + 1); } @Override public boolean moveToPrevious() { return moveToPosition(mPos - 1); } private boolean isPointingOnExtras() { if (-1 == mPos || getCount() == mPos) { throw new CursorIndexOutOfBoundsException(mPos, getCount()); } if (mPos <= extras.length - 1) { // this is a request on an extra value return true; } return false; } private Object getExtraValue(int columnIndex) { switch (columnIndex) { case ID_COLUMN_INDEX: return extras[mPos].getId(); case NAME_COLUMN_INDEX: return extras[mPos].getName(mContext); } return null; } @Override public int getInt(int columnIndex) { if (isPointingOnExtras()) return (Integer) getExtraValue(columnIndex); int res = super.getInt(columnIndex); return res; } @Override public String getString(int columnIndex) { if (isPointingOnExtras()) return getExtraValue(columnIndex).toString(); return super.getString(columnIndex); } public static class Playlist { private int mId; private int mNameResId; public Playlist(int mId, int nameResId) { this.mId = mId; this.mNameResId = nameResId; } public int getId() { return mId; } public String getName(Context mContext) { return mContext.getResources().getString(mNameResId); } } } 

El cursor original tiene 2 columnas (int, String), así que lo construyo con una matriz de objetos de filas extra.

Sé que esto un poste viejo, pero es un dolor verdadero que las filas no se pueden agregar manualmente a un cursor. He llegado con una solución cruda. Podría ser de alguna ayuda.

Cursor es en realidad una interface y puede crear una class personalizada que implements la interfaz Cursor .

 class ManualCursor implements Cursor{ // .... private Vector<String[]> rows; public void addRow(String[] values){ rows.add(values); } // Implement the necessary methods, getString(int), etc. //.... } 

Y finalmente en tu código

 if (cursors[i].getCount() == 0){ cursors[i] = new ManualCursor(); cursors[i].addRow(rowValues); } 

Deberias hacer eso. Pero ten cuidado, para que esto funcione, tienes que ser sabio al implementar la interfaz Cursor .

Lamentablemente, por lo que sé, no hay manera de que usted puede agregar manualmente datos al cursor. Usted necesita manejar esto de una manera diferente.

La única manera en que puedo pensar en que puedes hacer esto es

  • Haga una estructura con los campos de datos que necesita.
  • Haga un Arraylist y llene los objetos de su estructura con los datos de los cursores y agréguelos a la lista.
  • A continuación, agregue la información de número que falta manualmente y agréguela a la lista.
  • Pasa esta lista a tu adaptador, en caso de que pases un cursor a un adaptador ahora. Por supuesto, tendría que cambiar su implementación cursoradapter a un arrayadapter .
FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.