18

別の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に転送するのではなく、時間がかかりすぎます)。

4

3 に答える 3

10

カーソルを「アンラップ」する必要はありません。問題は、コンテンツプロバイダーが別のプロセスで実行されているクライアントに結果を提供している場合、query()から返されたカーソルが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;
    }
}
于 2011-03-09T09:51:41.867 に答える
1

2つのapkか何かを使用しているように聞こえます。同じアプリケーション内で相互に使用している異なるContentProviderでこれを取得するべきではありません。ただし、別のアプリケーションがContentProviderを使用しようとすると、このエラーが発生します。解決策は、カスタムカーソル実装にCrossProcessCursorインターフェイスを実装させることです。

于 2011-01-07T23:08:51.517 に答える
0

私の知る限り、ラッパークラスはプライベートであるため(リフレクションを使用して可能かもしれませんが、SecurityManagerはおそらくそれを許可しません)、カーソルをアンラップすることはできませんが、CrossProcessCursorを実装する独自のラッパーを作成して、カーソルが返され、ContentProviderによって返されます。

于 2010-12-10T15:45:58.053 に答える