ContentProvider 中的光标包装/展开

发布于 2024-09-28 10:08:30 字数 1111 浏览 9 评论 0原文

我正在创建 ContentProvider,它是另一个 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;
     }
    }

从我的 CP 调用内部 CP 后,我收到意外的异常:

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

该异常涉及 CP 对游标的包装并将其包装传输,外部 CP 无法再次包装它,所以我在这里遇到问题。当我检查返回的游标的类时,我收到了 CursorWrapperInner。

有没有什么方法可以在我的外部 CP 中解开光标(从这个 CWI 到常规光标)(但不是通过在循环中将所有数据传输到 MatrixCursor – 这太耗时了)。

I'm creating ContentProvider which is a proxy of another ContentProvider (for security issues and to give access to part of functionality of full app).

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

After calling inner CP from my CP I recive unexpected exception:

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

The exception concerns the wrapping of the Cursor by the CP and transfer it wrapped, Outer CP can't wrap it again so I have a problem here. When I checked class of returned cursor I received CursorWrapperInner.

Is there any way to unwrap cursor (from this CWI to regular Cursor) in my outer CP (but not by transfering all data to MatrixCursor in loop – it's too time-consuming).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

瀞厅☆埖开 2024-10-05 10:08:30

无需“展开”光标。问题是,如果您的内容提供程序向在另一个进程中运行的客户端提供结果,则从 query() 返回的 Cursor 必须实现 CrossProcessCursor 接口。文档(AFAICS)中没有说明,但您可以从日志中看到这一点。

您需要做的就是实现 CrossProcessCursor 接口,并将其包裹在您的光标周围。

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

CrossProcessCursor 方法的实现是从 AbstractCursor 移植的。进行了一些细微的修改,以便编译器满意:

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

There's no need to "unwrap" the cursor. The problem is, if your content provider is providing results to a client that runs in another process, the Cursor you returned from query() must implement CrossProcessCursor interface. It's not stated in document (AFAICS), but you can see this from your log.

All you need to do is implement CrossProcessCursor interface, and wrap it around your cursor.

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

Implementation of CrossProcessCursor methods are ported from AbstractCursor. Some slight modifications are made so the compiler's happy:

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;
    }
}
旧竹 2024-10-05 10:08:30

听起来你使用了两个 apk 之类的。您不应该在同一应用程序中使用彼此使用的不同 ContentProvider 来获得此信息。然而,当另一个应用程序尝试使用您的 ContentProvider 时,您会收到此错误。解决方案是让您的自定义 Cursor 实现实现 CrossProcessCursor 接口。

Sounds like you use two apk's or something. You shouldn't get this with different ContentProviders using eachother within the same application. When another application tries to use your ContentProviders however you get this error. Solution is to let your custom Cursor implementation implement the CrossProcessCursor interface.

哭泣的笑容 2024-10-05 10:08:30

据我所知,您无法解开 Cursor,因为包装类是私有的(可以使用反射,但 SecurityManager 可能不允许),但您可以尝试创建自己的包装器,它实现 CrossProcessCursor,包装返回光标并由您的 ContentProvider 返回。

As far as I know you can't unwrap the Cursor because the wrapper class is private (it could be possible using reflections but the SecurityManager won't allow it probably) but you could try to create your own wrapper which implements CrossProcessCursor, wraps the returned cursor and is returned by your ContentProvider.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文