1

ContentProviderクラスを使用するアプリがあります。openFileメソッドでは、ファイルをデコードしてデータのストリームとして返すことができる必要があります。そこで、ビルトインパイプを使うことにしました。

問題は、createPipeメソッドを使用すると、64KBしか書き込めないことです。その後、パイプにデータを書き込むことができなくなります。また、データが完全にデコードされてパイプに書き込まれるまで、読み取ることができないことに注意してください。

package com.aujas.html.viewer.content;
public class LocalFileContentProvider extends ContentProvider {

private static final String URI_PREFIX = "content://com.aujas.html.viewer.localfile.dec/";
public static File file;
public String filename;
public ParcelFileDescriptor[] parcels;

public static String constructUri(String url) {
    String editString = url.replaceAll("%20", " ");
    int n = editString.length();
    String uri = editString.substring(5, n - 1);
    Log.d("URI", uri);
    return URI_PREFIX + uri + "\"";
}

public ParcelFileDescriptor openFile(Uri uri, String mode) {

    Log.d("OPEN", uri.getPath());
    return parcels[0];

}

@Override
public boolean onCreate() {
    return true;
}

@Override
public int delete(Uri uri, String s, String[] as) {
    throw new UnsupportedOperationException(
            "Not supported by this provider");
}

@Override
public String getType(Uri uri) {
    throw new UnsupportedOperationException(
            "Not supported by this provider");
}

@Override
public Uri insert(Uri uri, ContentValues contentvalues) {
    throw new UnsupportedOperationException(
            "Not supported by this provider");
}

@Override
public Cursor query(Uri uri, String[] as, String s, String[] as1, String s1) {
    throw new UnsupportedOperationException(
            "Not supported by this provider");
}

@Override
public int update(Uri uri, ContentValues contentvalues, String s,
        String[] as) {
    throw new UnsupportedOperationException(
            "Not supported by this provider");
}

class DecryptAsync extends AsyncTask<String, Integer, String> {

    @Override
    protected String doInBackground(String... paramArrayOfParams) {
        // TODO Auto-generated method stub
        try {
            file = new File(paramArrayOfParams[0]);
            Log.d("DecrypOpened", file.toString());
            parcels = ParcelFileDescriptor.createPipe();
            Log.d("filebeindec", LocalFileContentProvider.file.toString());
            FileInputStream fis = new FileInputStream(LocalFileContentProvider.file);

            android.os.ParcelFileDescriptor.AutoCloseOutputStream out = new android.os.ParcelFileDescriptor.AutoCloseOutputStream(parcels[1]);
            Cipher ecipher;
            Cipher dcipher;
            SecretKey key;
            String input = "768f8a949de079da";
            byte[] encoded = new BigInteger(input, 16).toByteArray();
            key = new SecretKeySpec(encoded, "DES");
            byte[] iv = new byte[] { (byte) 0x8E, 0x12, 0x39, (byte) 0x9C,
                    0x07, 0x72, 0x6F, 0x5A };
            AlgorithmParameterSpec paramSpec = new IvParameterSpec(iv);
            ecipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
            dcipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
            ecipher.init(Cipher.ENCRYPT_MODE, key, paramSpec);
            dcipher.init(Cipher.DECRYPT_MODE, key, paramSpec);
            byte[] buf = new byte[1024];
            InputStream in = new CipherInputStream(fis, dcipher);
            int numRead = 0;
            int n = 1;
            while ((numRead = in.read(buf)) >= 0) {
                n++;
                out.write(buf, 0, numRead);
                Log.d("Error", "SD");
                if (n == 64) {
                    out.flush();
                    out.flush();
                    n = 0;
                }
            }

            Log.d("Decypt Done", out.toString());
        } catch (Exception e) {
            Log.d("AsyncError", e.toString());
        }
        return null;
    }

    @Override
    protected void onPostExecute(String result) {
        // TODO Auto-generated method stub
        super.onPostExecute(result);
    }

}

}

これを実行すると、64KBしか書き込めません。書き込みごとに1KBを使用するため、64ログを取得しますが、その後は何も起こりません。これらのパイプにサイズ制限はありますか?回避策はありますか?ありがとう&よろしくrtindru

4

2 に答える 2

7

Linux カーネル (少なくとも Android に組み込まれているバージョン) では、パイプに対して 64k のバッファー制限があります。

そのため、ファイル全体 (64k より大きい) を書き込むことはできません。あなたがしなければならないことは

a) パイプを作成する

b) このパイプに書き込む書き込みスレッドを作成します。ブロックし、リーダー スレッドがパイプからコンテンツを読み取るまで待機します。

c) このスレッドを開始する

d) リーダー ファイル記述子をクライアントに返します。

では、ライターとリーダーの両方が同時に書き込みと読み取りを行うようになります。ライターはバッファーがいっぱいになるとブロックし、リーダーはバッファーが空になるとブロックします。

于 2012-08-02T19:12:12.193 に答える
2

別の質問への回答で、@ victor-ronin の回答を @commonsware のコードを使用してコードに展開しました。

カスタム ContentProvider - openInputStream()、openOutputStream()

于 2013-02-06T17:38:41.797 に答える