android - studio - Cursor de ajuste/desenvolvimiento en ContentProvider
manual de programacion android pdf (3)
No hay necesidad de "desenvolver" 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 la consulta () debe implementar la interfaz CrossProcessCursor. No se indica en el documento (AFAICS), pero puede verlo desde su registro.
Todo lo que necesita hacer es implementar la interfaz de CrossProcessCursor y envolverla alrededor de su cursor.
// your query statement does not seem right..BTW
Cursor result = mContentResolver.query(...);
// now, you return a CrossProcessCursorWrapper.
return new CrossProcessCursorWrapper(result);
La implementación de los métodos de CrossProcessCursor se transporta desde AbstractCursor. Algunas modificaciones leves se hacen para que el compilador feliz:
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;
}
}
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).
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 al CP interno desde mi CP, recibí una 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 el CP y la transferencia envuelta, el CP Externo no puede envolverlo nuevamente, así que tengo un problema aquí. Cuando verifiqué la clase del cursor devuelto recibí CursorWrapperInner. ¿Hay alguna forma de desenvolver el cursor (de este CWI al cursor normal) en mi CP externo (pero no transfiriendo todos los datos a MatrixCursor en bucle? Es demasiado lento).
Parece que usas dos apk o algo así. No debe obtener esto con diferentes proveedores de contenido que se utilicen entre sí dentro de la misma aplicación. Cuando otra aplicación intenta usar su ContentProviders, sin embargo, recibe este error. La solución es permitir que su implementación de Cursor personalizada implemente la interfaz de CrossProcessCursor.
Por lo que sé, no puede desenvolver el Cursor porque la clase de envoltorio es privada (podría ser posible mediante el uso de reflexiones, pero el SecurityManager probablemente no lo permita), pero podría intentar crear su propio envoltorio que implemente el CrossProcessCursor, envuelve el cursor devuelto y es devuelto por su ContentProvider.