2010-10-20 15 views
18

Estoy creando ContentProvider, que es un proxy de otro ContentProvider (para problemas de seguridad y para dar acceso a parte de la funcionalidad de la aplicación completa).Envoltura/Desempaquetado de Cursor en 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; 
    } 
    } 

Después de llamar CP interior de mi CP I recive excepción inesperada:

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

La excepción se refiere a la envoltura del cursor por la CP y la transferencia envuelto, Outer CP no puede envolver de nuevo así que tengo un problema aquí. Cuando revisé la clase del cursor devuelto, recibí CursorWrapperInner. ¿Hay alguna forma de desenrollar el cursor (de este CWI a Cursor normal) en mi CP externo (pero no transfiriendo todos los datos a MatrixCursor en bucle, es demasiado lento).

Respuesta

10

No es necesario "desenrollar" el cursor. El problema es que si su proveedor de contenido proporciona resultados a un cliente que se ejecuta en otro proceso, el Cursor que devolvió de query() debe implementar la interfaz CrossProcessCursor. No aparece en el documento (AFAICS), pero puede verlo en su registro.

Todo lo que necesita hacer es implementar la interfaz CrossProcessCursor y colocarla alrededor del cursor.

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

Implementación de métodos CrossProcessCursor se transportan desde AbstractCursor. Se hacen algunas ligeras modificaciones para que el compilador esté contento:

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

Hasta donde yo sé, no puede desenvolver el Cursor porque la clase contenedora es privada (podría ser posible utilizando reflejos, pero el SecurityManager no lo permitirá) pero podría tratar de crear su propia envoltura que implemente CrossProcessCursor, ajusta el cursor devuelto y lo devuelve ContentProvider.

1

Parece que usas dos apk o algo así. No debería obtener esto con diferentes ContentProviders que se usan entre sí dentro de la misma aplicación. Cuando otra aplicación intenta usar tus ContentProviders, obtienes este error. La solución es permitir que su implementación personalizada de Cursor implemente la interfaz CrossProcessCursor.

Cuestiones relacionadas