尝试使用cwac提供程序发送pdf

时间:2016-07-22 15:33:19

标签: android commonsware-cwac share-intent

我无法让cwac工作,看着演示代码也没有帮助。我只是想通过股票意图导出pdf。目前输出是“不能附加空文件”#34;错误。但该文件确实存在,我无法判断问题是否与文件名,位置或cwac提供程序的使用有关。

以下是我设置提供商的方式。

        <provider
        android:name="com.commonsware.cwac.provider.StreamProvider"
        android:authorities="com.anothergamedesigner.CatVimeoTest.provider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="com.commonsware.cwac.provider.STREAM_PROVIDER_PATHS"
            android:resource="@xml/file_paths"/>
    </provider>

这是提供程序正在使用的xml资源。我设置路径为&#34;&#34;因为我没有任何子目录。我不知道这些是否是必需的,但理想情况下我不想将代码转换到其他位置,以便将文件放在子目录中。虽然,如果这是问题,我想我可以,但我不明白为什么根本不应该工作。

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <asset name="assets" path=""/>
</paths>

这是我的PDFActivity(扩展AppCompatActivity):

变量:

private String pdfName //set in onCreate; ex. "This is my.pdf"

private static final String AUTHORITY = "com.anothergamedesigner.CatVimeoTest";
private static final Uri PROVIDER = Uri.parse("content://"+AUTHORITY);
private static final String ASSET_PATHS ="assets/";

方法定义:

private Intent getOpenPDFShareIntent(String name){
    Intent shareIntent = new Intent(android.content.Intent.ACTION_SEND);
    shareIntent.setType("application/pdf");

    shareIntent.putExtra(android.content.Intent.EXTRA_EMAIL, new String[] {""});
    shareIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, getResources().getString(R.string.default_share_subject));
    shareIntent.putExtra(android.content.Intent.EXTRA_TEXT, getResources().getString(R.string.default_share_text));

    shareIntent.putExtra(Intent.EXTRA_STREAM, getURI());
    shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    shareIntent.setType("text/plain");
    return shareIntent;
}

private Uri getURI(){
    String path = ASSET_PATHS + pdfName;
    return(PROVIDER
            .buildUpon()
            .appendPath(StreamProvider.getUriPrefix(AUTHORITY))
            .appendPath(path)
            .build());

}

在getURI()中,System.out.println(path)的示例返回值是:&#34; assets / my.pdf&#34;

代码通过选择的菜单按钮运行:

Intent shareIntent = getOpenPDFShareIntent(pdfName);
StartActivity(Intent.createChooser(shareIntent, getResources().getString(R.string.contact_send_mail));

编辑: 试图删除null URIPrefix:

    private Uri getURI(){
    //String path = ASSET_PATHS + pdfName;

    if(StreamProvider.getUriPrefix(AUTHORITY) != null){
        return(PROVIDER
                .buildUpon()
                .appendPath(StreamProvider.getUriPrefix(AUTHORITY))
                .appendPath(ASSET_PATHS)
                .appendPath(pdfName)
                .build());
    } else{
        return(PROVIDER
                .buildUpon()
                .appendPath(ASSET_PATHS)
                .appendPath(pdfName)
                .build());
    }
}

编辑2 - 使用DocumentFile进行测试:

我从另一个SO答案中使用了这些新方法,并将其更改为返回文件。

private File CopyReadAssets()
{
    AssetManager assetManager = getAssets();

    InputStream in = null;
    OutputStream out = null;
    File file = new File(getFilesDir(), "my.pdf");
    try
    {
        in = assetManager.open("my.pdf");
        out = openFileOutput(file.getName(), Context.MODE_WORLD_READABLE);

        copyFile(in, out);
        in.close();
        in = null;
        out.flush();
        out.close();
        out = null;
    } catch (Exception e)
    {
        Log.e("tag", e.getMessage());
    }

    return file;
}

private void copyFile(InputStream in, OutputStream out) throws IOException
{
    byte[] buffer = new byte[1024];
    int read;
    while ((read = in.read(buffer)) != -1)
    {
        out.write(buffer, 0, read);
    }
}

然后我测试了使用:

DocumentFile aFile = DocumentFile.fromFile(CopyReadAssets());
DocumentFile file = DocumentFile.fromSingleUri(this, getURI());
System.out.println(aFile.getName());
System.out.println(aFile.length());
System.out.println(file.getName());
System.out.println(file.length());

它返回&#34; my.pdf&#34;和&#34; 33528&#34;对于aFile和&#34; my.pdf&#34;和&#34; FileNotFoundException&#34;对于文件。

2 个答案:

答案 0 :(得分:0)

content://com.anothergamedesigner.CatVimeoTest/null/assets%2FCEGA%20OnBoard%20Su‌​pport%201.6.compressed.pdf

我可以看到这里有两个问题。

首先,StreamProvider.getUriPrefix(AUTHORITY)正在返回null。我不知道为什么,因为你似乎不是子类StreamProvider。话虽如此,您应该检查null并跳过appendPath()语句,如果它是null

其次,使用两个ASSET_PATHS + pdfName语句而不是appendPath()。这样可以防止/转换为%2F

请注意,我没有尝试过在文件名中包含空格的文件,或其他任何必须转义的文件。可能存在与此相关的错误。如果更改上述两项无效,请尝试暂时将PDF重命名为简单的内容。如果 然后工作,我有一个我需要修复的错误。

答案 1 :(得分:0)

最终法典

问题似乎在于ASSET_PATHS。将pdfName附加到&#34; assets&#34;由于某种原因被证明是有问题的。因此,我选择从final中更改ASSET_PATHS,然后在onCreate方法中设置它。这可能是一种方法,或者您可以在不同的pdf中进行硬编码,例如在演示项目中。

public class PDFViewActivity extends AppCompatActivity {

private String pdfName;
...

private static final String AUTHORITY = "com.your.provider";
private static final Uri PROVIDER = Uri.parse("content://"+AUTHORITY);
private static String ASSET_PATHS;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    Bundle extras = getIntent().getExtras();
    pdfName = extras.getString("pdfName");
    ...

    ASSET_PATHS = "assets/" + pdfName;

    // Place an PDFViewFragment as our content pane
    PDFViewFragment f = new PDFViewFragment();
    getSupportFragmentManager().beginTransaction().add(android.R.id.content, f).commit();
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.menu_pdf, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle item selection
    switch (item.getItemId()) {
        case R.id.menu_button_share:
            Intent shareIntent = getOpenPDFShareIntent();
            startActivity(Intent.createChooser(shareIntent, "Send Email"));
            return true;
        ...
        default:
            return super.onOptionsItemSelected(item);
    }
}

private Intent getOpenPDFShareIntent(){
    Intent shareIntent = new Intent(Intent.ACTION_SEND);
    shareIntent.setType("application/pdf");

    shareIntent.putExtra(android.content.Intent.EXTRA_EMAIL, new String[] {""});
    shareIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, getResources().getString(R.string.default_share_subject));
    shareIntent.putExtra(android.content.Intent.EXTRA_TEXT, getResources().getString(R.string.default_share_text));
    shareIntent.putExtra(Intent.EXTRA_STREAM, getURI());
    shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    shareIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);

    return shareIntent;
}

private Uri getURI(){
    return(PROVIDER
            .buildUpon()
            .appendPath(StreamProvider.getUriPrefix(AUTHORITY))
            .appendPath(ASSET_PATHS)
            .build());
}

}