2010-10-20 13 views
18

Sto creando ContentProvider che è un proxy di un altro ContentProvider (per problemi di sicurezza e per dare accesso a parte delle funzionalità dell'app completa).Cursor Wrapping/Unwrapping in ContentProvider

public class GFContactsProvider extends ContactsProvider implements 
     DatabaseConstants { 
    private Context mContext; 
    private ContentResolver mContentResolver; 
    @Override 
    public boolean onCreate() { 
     mContext = getContext(); 
     mContentResolver = mContext.getContentResolver(); 


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

    Cursor result = mContentResolver.query(ContactsContract.getContactsURI(Long.parseLong(address.get(1))), null, null, null, ContactsContract.ContactColumns.SHOW_NAME); 
return result; 
    } 
    } 

Dopo aver chiamato CP interna dal mio CP ho recive eccezione imprevista:

java.lang.UnsupportedOperationException: Only CrossProcessCursor cursors are supported across process for now 

L'eccezione riguarda l'avvolgimento del cursore dal CP e trasferirlo avvolto, esterno CP non può avvolgerlo di nuovo quindi ho un problema qui. Quando ho controllato la classe del cursore restituito, ho ricevuto CursorWrapperInner. C'è un modo per scartare il cursore (da questo CWI al Cursore normale) nel mio CP esterno (ma non trasferendo tutti i dati su MatrixCursor in loop - è troppo dispendioso in termini di tempo).

risposta

10

Non è necessario "scartare" il cursore. Il problema è che se il provider di contenuti fornisce risultati a un client eseguito in un altro processo, il cursore che è stato restituito da query() deve implementare l'interfaccia di CrossProcessCursor. Non è indicato nel documento (AFAICS), ma puoi vederlo dal tuo registro.

Tutto ciò che dovete fare è implementare l'interfaccia CrossProcessCursor e avvolgerlo intorno al vostro cursore.

// your query statement does not seem right..BTW 
Cursor result = mContentResolver.query(...); 
// now, you return a CrossProcessCursorWrapper. 
return new CrossProcessCursorWrapper(result); 

L'implementazione dei metodi CrossProcessCursor viene eseguita da AbstractCursor. Alcune piccole modifiche sono fatte in modo che il compilatore sia felice:

public class CrossProcessCursorWrapper extends CursorWrapper implements 
     CrossProcessCursor { 
    public CrossProcessCursorWrapper(Cursor cursor) { 
     super(cursor); 
    } 

    @Override 
    public CursorWindow getWindow() { 
     return null; 
    } 

    @Override 
    public void fillWindow(int position, CursorWindow window) { 
     if (position < 0 || position > getCount()) { 
      return; 
     } 
     window.acquireReference(); 
     try { 
      moveToPosition(position - 1); 
      window.clear(); 
      window.setStartPosition(position); 
      int columnNum = getColumnCount(); 
      window.setNumColumns(columnNum); 
      while (moveToNext() && window.allocRow()) { 
       for (int i = 0; i < columnNum; i++) { 
        String field = getString(i); 
        if (field != null) { 
         if (!window.putString(field, getPosition(), i)) { 
          window.freeLastRow(); 
          break; 
         } 
        } else { 
         if (!window.putNull(getPosition(), i)) { 
          window.freeLastRow(); 
          break; 
         } 
        } 
       } 
      } 
     } catch (IllegalStateException e) { 
      // simply ignore it 
     } finally { 
      window.releaseReference(); 
     } 
    } 

    @Override 
    public boolean onMove(int oldPosition, int newPosition) { 
     return true; 
    } 
} 
0

Per quanto ne so, non è possibile scartare il cursore perché la classe wrapper è privata (potrebbe essere possibile utilizzare le riflessioni ma SecurityManager non lo consente probabilmente) ma si potrebbe provare a creare il proprio wrapper che implementa CrossProcessCursor, avvolge il cursore restituito e viene restituito dal ContentProvider.

1

Sembra che tu usi due apk o qualcosa del genere. Non si dovrebbe ottenere ciò con ContentProvider diversi che si utilizzano tra loro all'interno della stessa applicazione. Quando un'altra applicazione tenta di utilizzare ContentProvider, tuttavia, si ottiene questo errore. La soluzione è lasciare che l'implementazione personalizzata del Cursore implementa l'interfaccia CrossProcessCursor.

Problemi correlati