androidcursorwrappercross-process

How to implement a CrossProcessCursor compatible generic custom CursorWrapper


I manage to create a working CursorWrapper, but get stuck when I want to use my ContentProvider across processes.

These posts even show how to implement the CrossProcessCursor interface, notably the hard and undocumented fillWindow() method:

The problem is that I can think only of an implementation of fillWindow() that deals with a cursor with either all columns containing Blobs, or Strings, or ..., but not a mix of those, as a real-world cursor is bound to have. The real issue here is a lack of a getType() function (exists only from v11 on), or a getRaw()/putRaw() that would just copy binary without complaining. How do you deal with this without incurring unwanted conversions in your returned cursor values?


Solution

  • I've implemented it as follows for now, but it does not feel like the right thing to do or robust:

    /**
     * Copy data from cursor to CursorWindow
     * @param position start position of data
     * @param window
     */
    public void fillWindow(int position, CursorWindow window) {
        if (position < 0 || position > getCount()) {
            return;
        }
        window.acquireReference();
        try {
            int oldpos = this.getPosition();
            this.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++) {
    
                    //int type = getType(i);//only from v11 on
    
                    try {
                        String field7 = getString(i);
                        if (field7 != null) {
                            try {
                                    if (!window.putLong(new Long(field7), this.getPosition(), i)) {
                                        if (!window.putDouble(new Double(field7), this.getPosition(), i)) {
                                            if (!window.putString(field7, this.getPosition(), i)) {
                                                window.freeLastRow();
                                                break;
                                            }
                                        }
                                    }
                                } catch (NumberFormatException e) {
                                    try {
                                        if (!window.putDouble(new Double(field7), this.getPosition(), i)) {
                                            if (!window.putString(field7, this.getPosition(), i)) {
                                                window.freeLastRow();
                                                break;
                                            }
                                        }
                                    } catch (NumberFormatException e1) {
                                        if (!window.putString(field7, this.getPosition(), i)) {
                                            window.freeLastRow();
                                            break;
                                        }
                                    }
                                }
                        } else {
                            if (!window.putNull(this.getPosition(), i)) {
                                window.freeLastRow();
                                break;
                            }
                        }
                    } catch (SQLiteException e7) {
    
                        try {
                            byte[] field1 = getBlob(i);
                            if (field1 != null) {
                                if (!window.putBlob(field1, this.getPosition(), i)) {
                                    window.freeLastRow();
                                    break;
                                }
                            } else {
                                if (!window.putNull(this.getPosition(), i)) {
                                    window.freeLastRow();
                                    break;
                                }
                            }
                        } catch (SQLiteException e1) {
                            throw e1;
                        }
                    }
                }
            }
    
            this.moveToPosition(oldpos);
        } catch (IllegalStateException e){
            // simply ignore it
        } finally {
            window.releaseReference();
        }
    }