【问题标题】:How to open a pdf stored either in res/raw or assets folder?如何打开存储在 res/raw 或 assets 文件夹中的 pdf?
【发布时间】:2011-09-23 09:19:39
【问题描述】:

我将在我的应用程序中显示一个 pdf,并且该 pdf 必须与应用程序捆绑在一起。

有什么好的方法可以做到这一点?

我已经读到可以通过将 pdf 文件添加到 res/raw 文件夹并从那里读取它来做到这一点,但是当我将 pdf 文件放在那里时会出现项目错误。

所以我尝试将pdf文件放在项目的asset文件夹中,它没有报错。

这就是我尝试显示 pdf 的方式:

File pdfFile = new File("res/raw/file.pdf");
Uri path = Uri.fromFile(pdfFile);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(path, "application/pdf");
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

有什么想法或建议吗?

提前致谢

【问题讨论】:

    标签: android file pdf assets


    【解决方案1】:

    我的答案有各种各样的问题,所以我整理了一些可行的方法。

    布局

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        >
    
    
        <ImageView
            android:id="@+id/image_pdf"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_above="@+id/btn_okay"
            android:layout_margin="5dp"/>
    
        <Button
            android:id="@+id/btn_okay"
            android:layout_width="80dp"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:layout_alignParentRight="true"
            android:layout_margin="10dp"
            android:text="@string/ok"/>
    
    </RelativeLayout>
    

    代码

    /**
     * Render a page of a PDF into ImageView
     * @param targetView
     * @throws IOException
     */
    private void openPDF(ImageView targetView) throws IOException {
    
        //open file in assets
    
        ParcelFileDescriptor fileDescriptor;
    
        String FILENAME = "your.pdf";
    
        // Create file object to read and write on
        File file = new File(getActivity().getCacheDir(), FILENAME);
        if (!file.exists()) {
            AssetManager assetManager = getActivity().getAssets();
            FileUtils.copyAsset(assetManager, FILENAME, file.getAbsolutePath());
        }
    
        fileDescriptor = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
    
        PdfRenderer pdfRenderer = new PdfRenderer(fileDescriptor);
    
        //Display page 0
        PdfRenderer.Page rendererPage = pdfRenderer.openPage(0);
        int rendererPageWidth = rendererPage.getWidth();
        int rendererPageHeight = rendererPage.getHeight();
        Bitmap bitmap = Bitmap.createBitmap(
                rendererPageWidth,
                rendererPageHeight,
                Bitmap.Config.ARGB_8888);
        rendererPage.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY);
    
        targetView.setImageBitmap(bitmap);
        rendererPage.close();
        pdfRenderer.close();
    }
    
    
    public static boolean copyAsset(AssetManager assetManager, String fromAssetPath, String toPath) {
        InputStream in = null;
        OutputStream out = null;
        try {
            in = assetManager.open(fromAssetPath);
            new File(toPath).createNewFile();
            out = new FileOutputStream(toPath);
            copyFile(in, out);
            in.close();
            in = null;
            out.flush();
            out.close();
            out = null;
            return true;
        } catch(Exception e) {
            e.printStackTrace();
            return false;
        }
    }
    
    public static 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);
        }
    }
    

    【讨论】:

      【解决方案2】:

      您不能直接assets文件夹打开pdf文件。您必须先将文件从assets文件夹写入sd卡,然后再从sd卡读取。代码如下:-

           @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
      
          File fileBrochure = new File(Environment.getExternalStorageDirectory() + "/" + "abc.pdf");
          if (!fileBrochure.exists())
          {
               CopyAssetsbrochure();
          } 
      
          /** PDF reader code */
          File file = new File(Environment.getExternalStorageDirectory() + "/" + "abc.pdf");      
      
          Intent intent = new Intent(Intent.ACTION_VIEW);
          intent.setDataAndType(Uri.fromFile(file),"application/pdf");
          intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
          intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
          try 
          {
              getApplicationContext().startActivity(intent);
          } 
          catch (ActivityNotFoundException e) 
          {
               Toast.makeText(SecondActivity.this, "NO Pdf Viewer", Toast.LENGTH_SHORT).show();
          }
      }
      
      //method to write the PDFs file to sd card
          private void CopyAssetsbrochure() {
              AssetManager assetManager = getAssets();
              String[] files = null;
              try 
              {
                  files = assetManager.list("");
              } 
              catch (IOException e)
              {
                  Log.e("tag", e.getMessage());
              }
              for(int i=0; i<files.length; i++)
              {
                  String fStr = files[i];
                  if(fStr.equalsIgnoreCase("abc.pdf"))
                  {
                      InputStream in = null;
                      OutputStream out = null;
                      try 
                      {
                        in = assetManager.open(files[i]);
                        out = new FileOutputStream(Environment.getExternalStorageDirectory() + "/" + files[i]);
                        copyFile(in, out);
                        in.close();
                        in = null;
                        out.flush();
                        out.close();
                        out = null;
                        break;
                      } 
                      catch(Exception e)
                      {
                          Log.e("tag", e.getMessage());
                      } 
                  }
              }
          }
      
       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);
              }
          }
      

      仅此而已..享受!请不要忘记给+1。谢谢

      【讨论】:

      • 作为新版本中的 Lint 建议.. 不要硬编码 /sdcard/;改用Environment.getExternalStorageDirectory().getPath()
      • Environment.getExternalStorageDirectory().getPath() + "/" 使这个例子工作
      • 用户阅读后如何删除pdf?我尝试使用 startActivityForResult 但没有运气
      【解决方案3】:

      我使用以下格式从我自己的应用程序中打开原始资源。我还没有测试其他应用程序是否可以打开您的原始资源。

      Uri path = Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.myPdfName);
      

      【讨论】:

      • 嗯,我的设备上安装了 adobe 阅读器,但我得到了 ActivitynotFoundException。有什么想法吗?
      • 无法匹配 URI 或 mime 类型(或两者),遗憾的是我不知道 Reader 应用程序如何匹配。您可能必须尝试指定或不指定 mime 类型,并尝试从 SD 卡打开某些内容,因为它可能根本无法从您的原始资源中打开。
      【解决方案4】:

      你的 pdf 意图看起来不错,但你应该尝试这个来获取原始文件夹中文件的 Uri:

      Uri path = Uri.parse("android.resource://<you package>/raw/<you file.pdf>");
      

      (Source)

      【讨论】:

        【解决方案5】:

        我的应用程序需要在外部应用程序的原始数据中打开一个 pdf 文件内容... 我写:

        public class MainActivity extends Activity {
        
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            Button button = (Button) findViewById(R.id.OpenPdfButton);
            button.setOnClickListener(new View.OnClickListener() {
                InputStream is = getResources().openRawResource(R.raw.filepdf);
        
                @Override
                public void onClick(View v) {
                   startpdf();
                 }
                   private void startpdf() {
                    // TODO Auto-generated method stub
        
                    File file = new File("R.id.filepdf");
        
                    if (file.exists()) {
                        Uri path = Uri.fromFile(file);
                        Intent intent = new Intent(Intent.ACTION_VIEW);
                        intent.setDataAndType(path, "application/pdf");
                        intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        
                        try {
                            startActivity(intent);
                        } 
                        catch (ActivityNotFoundException e) {
        
                        }
                    }
                }
        
        
            });
        }
        }
        

        【讨论】:

          【解决方案6】:

          如果您的应用程序实际上实现了 PDF 阅读器,您将能够从 raw/assets/ 显示它。由于您希望它显示在单独的应用程序(例如 Adob​​e Reader)中,我建议您执行以下操作:

          1. 将 PDF 文件存储在 assets/ 目录中。
          2. 当用户想要查看它时,请将其复制到 public 的某个位置。查看openFileOutputgetExternalFilesDir
          3. 像现在一样启动Intent,除了在新创建的文件上使用getAbsolutePath() 来存储意图的数据。

          请注意,用户可能没有 PDF 阅读应用程序。在这种情况下,捕获ActivityNotFoundException 并显示适当的消息很有用。

          【讨论】:

          • 您可以使用 PackageManager 的 queryIntentActivities 方法来检查是否有任何活动可以响应给定的 Intent。示例见here
          • @David 我知道我忘记了什么!感谢您添加。
          • :) 我觉得你的答案是最好的解决方案,除非外部应用程序可以访问包资源。
          猜你喜欢
          • 1970-01-01
          • 2012-06-24
          • 2014-06-17
          • 1970-01-01
          • 2011-12-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多