2012-03-29 11 views
14

Ho una serie di numeri di telefono e desidero ottenere i nomi dei contatti corrispondenti dal database dei contatti.Aggiunta manuale di righe al cursore

Nella serie di numeri di telefono, ho anche alcuni numeri che non sono stati salvati prima nel database dei contatti. Per esempio;

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

ho la matrice contenente i numeri di telefono sopra indicato, vale a dire 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() restituisce 2 nello scenario precedente. Quando il numero di telefono non appare nella lista dei contatti, il cursore diventa vuoto e in qualche modo quando li unisco non contribuisce affatto. Quello che voglio è quello di avere un cursore come segue

telefoni cursore -> {Tim, Jim, 1111111}

penso di poter fare questo aggiungendo manualmente la riga come segue:

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 

Come posso ottenere questo?

Ecco la PEOPLE_PROJECTION

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

per favore dai un'occhiata alla mia soluzione, e vota se risolve il problema =) – elgui

+0

Rivedi la risposta che hai accettato, sembra essere sbagliato in base alle funzionalità attualmente disponibili dell'SDK di Android. –

+0

Bene, quando ho accettato la risposta, mi sembrava ragionevole. Lo esaminerò quando avrò un po 'di tempo libero. – 0x5f3759df

risposta

43

Il modo più semplice per aggiungere righe in un cursore è utilizzare un MatrixCursor e un MergeCursor. Queste due classi provengono dall'SDK e qui per risolvere questo tipo di problemi.

Fondamentalmente quello che fai è:

  1. Mettere le righe che si desidera aggiungere in una MatrixCusror
  2. Unisci la tua cursor e la tua matrixCursor utilizzando un MergeCursor

Qualcosa di simile:

// 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. 
+0

Vuoi metterlo in cima al metodo bindView? –

+0

Penso che sia meglio farlo prima di passare il cursore all'adattatore. Subito dopo aver effettuato la query. –

+4

aggiungi quale sarebbe l'indice di questa nuova riga in 'mergeCursor'? – Nezam

1

Purtroppo, Per quanto ne so, non c'è modo che è possibile aggiungere manualmente i dati al cursore. Devi gestirlo in un modo diverso.

L'unico modo che mi viene in mente in cui è possibile fare questo è

  • Fai una struttura con i campi dei dati necessari.
  • Crea un arraylist e riempi gli oggetti della tua struttura con i dati dei cursori e aggiungili all'elenco.
  • Ora aggiungere manualmente le informazioni sul numero mancante e aggiungerle all'elenco.
  • Passa questo elenco all'adattatore, nel caso tu stia passando un cursore ad un adattatore ora. Ovviamente dovresti modificare l'implementazione cursoradapter in un arrayadapter.
+0

Beh, questo non è quello che voglio sentire :) Comunque grazie per aver risposto – 0x5f3759df

+0

Ya lo so. È un grande dolore. Ho maledetto molto perché ho affrontato questo numero di volte. Tuttavia, se riesci a trovare un modo per aggiungere al cursore (cosa di cui dubito davvero), condividi su questo post. E come ripiego potresti usare questo metodo. – Shubhayu

+1

per favore dare un'occhiata alla mia soluzione, potrebbe risolvere il problema =) – elgui

2

So che questo è un vecchio post, ma è un vero dolore che le righe non possano essere aggiunte manualmente a un cursore. Ho trovato una soluzione grezza. Potrebbe essere di aiuto.

Cursor è in realtà un interface e si può creare un custom class che implements l'interfaccia Cursor.

class ManualCursor implements Cursor{ 
     // .... 
     private Vector<String[]> rows; 

     public void addRow(String[] values){ 
      rows.add(values); 
     } 

     // Implement the necessary methods, getString(int), etc. 

     //.... 
} 

E finalmente nel codice

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

Che dovrebbe farlo.Ma attenzione, però, perché funzioni, devi essere saggio mentre implementa l'interfaccia Cursor.

3

Io uso una soluzione che fa il trucco per tutte le mie diverse esigenze e che è più semplice dell'implementazione del Cursore.
Ecco un esempio in cui devo aggiungere righe "playlist" aggiuntive a un cursore, recuperate dal Mediastore. I aggiungere righe in primi indici del cursore originale:

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

} 
} 

cursore originale ha 2 colonne (int, String), quindi costruirlo con una matrice di righe oggetti extra.

+1

questo è fantastico .. grazie mille – amithgc