2016-07-22 35 views
1

我不能完全得到cwac工作,看演示代碼沒有幫助。我只是試圖通過共享意圖導出PDF。目前輸出是「無法附加空文件」錯誤。但該文件確實存在,並且我無法確定問題出在文件名,位置或cwac提供程序用法上。試圖發送一個pdf使用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資源供應商正在使用。我將路徑設置爲「」,因爲我沒有任何子目錄。我不知道這些是否是必需的,但理想情況下,我不想在其他位置切換我的代碼,以便將文件置於子目錄中進行必要的文件重構。雖然,如果這是問題,我想我可以,但我不明白爲什麼根不應該工作。

<?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(),一個例子回報系統。 out.println(路徑)是:「assets/my.pdf」

與DocumentFile測試 -

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:

我用這些

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

編輯: 試圖刪除空URIPrefix

的代碼通過一個菜單按鈕上選擇運行來自另一個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()); 

它返回å文件 「my.pdf」 和 「33528」 和 「my.pdf」 和 「FileNotFoundException異常」 的文件。

+0

我會通過固定的MIME類型開始。你沒有分享純文字。你正在共享'application/pdf',並且你正在調用'setType()'兩次。此外,擺脫'EXTRA_TEXT',直到你得到的東西工作。 'ACTION_SEND'支持* EXTRA_TEXT *或*'EXTRA_STREAM',所以你可能會得到一個或另一個,但不是兩者,這取決於ACTION_SEND活動的實現。除此之外,整個'Uri'看起來像從getURI()那裏得到的? – CommonsWare

+0

我已經註釋了這些行,是的,注意到setType的東西,並刪除它。同樣的問題,但可能最好按你的建議去做。 URI是: 內容://com.anothergamedesigner.CatVimeoTest/null/assets%2FCEGA%20OnBoard%20Support%201.6.compressed.pdf – NappyXIII

+0

任何想法如何空白部分可能產生? – NappyXIII

回答

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重命名爲簡單。如果然後工作,我有一個錯誤,我需要修復。

+0

我試着照你所說的做,但我注意到的第一件事是返回的URI是「content://com.anothergamedesigner.CatVimeoTest/assets%2F/CEGA%20OnBoard%20Support%201.6.compressed.pdf」 因此, /仍在轉換中。 – NappyXIII

+0

@NappyXIII:對不起,你也應該從'ASSET_PATHS'中刪除斜線。 – CommonsWare

+0

是的,意識到這一點,只是修復它哈哈。 – NappyXIII

0

FINAL CODE

問題是似乎是與ASSET_PATHS。由於某種原因,將pdfName附加到「assets」被證明是有問題的。正因爲如此,我選擇從最後一個更改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()); 
} 

}