【问题标题】:How to open a PDF via Intent from SD card如何通过 Intent 从 SD 卡打开 PDF
【发布时间】:2012-05-18 19:32:09
【问题描述】:

我正在尝试启动 Intent 以在我的应用程序的资产文件夹中打开一个 pdf。我已经阅读了几十篇文章,但仍然卡住了。显然我需要先将 pdf 复制到 sd 卡,然后启动 Intent。还是不行。

我认为问题出在Intent 启动,所以我只是尝试打开使用此代码复制到 SD 卡上的文件“example.pdf”:

Log.w("IR", "TRYING TO RENDER: " + Environment.getExternalStorageDirectory().getAbsolutePath()+"/example.pdf");
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.parse(Environment.getExternalStorageDirectory().getAbsolutePath()+"/example.pdf"), "application/pdf");
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

try {
    startActivity(intent);
    Log.e("IR", "No exception");
} 
catch (ActivityNotFoundException e) {
    Log.e("IR", "error: " + e.getMessage());
    Toast.makeText(InvestorRelations.this, 
        "No Application Available to View PDF", 
        Toast.LENGTH_SHORT).show();
}

这是我的 LogCat 输出。

05-10 10:35:10.950: W/IR(4508): TRYING TO RENDER: /mnt/sdcard/example.pdf
05-10 10:35:10.960: E/IR(4508): No exception

除非运行此代码,否则我会得到以下 Toast(不是由我的应用生成)

“不支持的文档类型”

但我可以通过安装的 PDF 查看应用手动打开文档。任何帮助将不胜感激。

【问题讨论】:

    标签: android pdf android-intent


    【解决方案1】:

    对于 Android Nougat 及更高版本,必须完成更多工作,否则应用将无法打开 .pdf 文件。我们必须使用FileProviderURI 设置一个临时权限:

     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
         File file=new File(mFilePath);
         Uri uri = FileProvider.getUriForFile(this, getPackageName() + ".provider", file);
         intent = new Intent(Intent.ACTION_VIEW);
         intent.setData(uri);
         intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
         startActivity(intent);
     } else {
         intent = new Intent(Intent.ACTION_VIEW);
         intent.setDataAndType(Uri.parse(mFilePath), "application/pdf");
         intent = Intent.createChooser(intent, "Open File");
         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
         startActivity(intent);
     }
    

    【讨论】:

    • 我这边+1。对于那些没有从Uri.parse()获取pdf路径的人可以使用intent.setDataAndType(Uri.fromFile(file), "application/pdf");
    • 这个答案不完整,你也必须在清单中定义提供者......
    【解决方案2】:

    此代码允许从您的 SD 卡中提取 pdf 文件

    Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
    intent.setType("application/pdf");
    startActivityForResult(intent, 200);
    

    【讨论】:

      【解决方案3】:

      现在接受的答案已经过时了。将FileProvider 用于file sharing

      【讨论】:

        【解决方案4】:

        从这里下载源代码 (Open pdf file from sdcard in android programmatically)

        添加这个依赖:

        compile ‘com.github.barteksc:android-pdf-viewer:2.0.3’
        

        activity_main.xml:

        <?xml version=”1.0″ encoding=”utf-8″?>
        <RelativeLayout xmlns:android=”http://schemas.android.com/apk/res/android&#8221;
        xmlns:tools=”http://schemas.android.com/tools&#8221;
        android:id=”@+id/activity_main”
        android:layout_width=”match_parent”
        android:layout_height=”match_parent”
        android:background=”#efefef”>
        
        <ListView
        android:layout_width=”match_parent”
        android:id=”@+id/lv_pdf”
        android:divider=”#efefef”
        android:layout_marginLeft=”10dp”
        android:layout_marginRight=”10dp”
        android:layout_marginTop=”10dp”
        android:layout_marginBottom=”10dp”
        android:dividerHeight=”5dp”
        android:layout_height=”wrap_content”>
        
        </ListView>
        </RelativeLayout>
        

        MainActivity.java:

        package com.pdffilefromsdcard;
        
        import android.Manifest;
        import android.app.ProgressDialog;
        import android.content.Intent;
        import android.content.pm.PackageManager;
        import android.os.Environment;
        import android.support.v4.app.ActivityCompat;
        import android.support.v4.content.ContextCompat;
        import android.support.v7.app.AppCompatActivity;
        import android.os.Bundle;
        import android.util.Log;
        import android.view.View;
        import android.widget.AdapterView;
        import android.widget.ListView;
        import android.widget.Toast;
        
        import java.io.File;
        import java.util.ArrayList;
        import java.util.HashMap;
        import java.util.List;
        
        public class MainActivity extends AppCompatActivity {
        
        ListView lv_pdf;
        public static ArrayList<File> fileList = new ArrayList<File>();
        PDFAdapter obj_adapter;
        public static int REQUEST_PERMISSIONS = 1;
        boolean boolean_permission;
        File dir;
        
        @Override
        protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        init();
        
        }
        
        private void init() {
        
        lv_pdf = (ListView) findViewById(R.id.lv_pdf);
        dir = new File(Environment.getExternalStorageDirectory().getAbsolutePath());
        fn_permission();
        lv_pdf.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
        Intent intent = new Intent(getApplicationContext(), PdfActivity.class);
        intent.putExtra(“position”, i);
        startActivity(intent);
        
        Log.e(“Position”, i + “”);
        }
        });
        }
        
        public ArrayList<File> getfile(File dir) {
        File listFile[] = dir.listFiles();
        if (listFile != null && listFile.length > 0) {
        for (int i = 0; i < listFile.length; i++) {
        
        if (listFile[i].isDirectory()) {
        getfile(listFile[i]);
        
        } else {
        
        boolean booleanpdf = false;
        if (listFile[i].getName().endsWith(“.pdf”)) {
        
        for (int j = 0; j < fileList.size(); j++) {
        if (fileList.get(j).getName().equals(listFile[i].getName())) {
        booleanpdf = true;
        } else {
        
        }
        }
        
        if (booleanpdf) {
        booleanpdf = false;
        } else {
        fileList.add(listFile[i]);
        
        }
        }
        }
        }
        }
        return fileList;
        }
        private void fn_permission() {
        if ((ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)) {
        
        if ((ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this, android.Manifest.permission.READ_EXTERNAL_STORAGE))) {
        } else {
        ActivityCompat.requestPermissions(MainActivity.this, new String[]{android.Manifest.permission.READ_EXTERNAL_STORAGE},
        REQUEST_PERMISSIONS);
        
        }
        } else {
        boolean_permission = true;
        
        getfile(dir);
        
        obj_adapter = new PDFAdapter(getApplicationContext(), fileList);
        lv_pdf.setAdapter(obj_adapter);
        
        }
        }
        
        @Override
        public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == REQUEST_PERMISSIONS) {
        
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
        
        boolean_permission = true;
        getfile(dir);
        
        obj_adapter = new PDFAdapter(getApplicationContext(), fileList);
        lv_pdf.setAdapter(obj_adapter);
        
        } else {
        Toast.makeText(getApplicationContext(), “Please allow the permission”, Toast.LENGTH_LONG).show();
        
        }
        }
        }
        
        }
        

        activity_pdf.xml:

        <?xml version=”1.0″ encoding=”utf-8″?>
        <LinearLayout xmlns:android=”http://schemas.android.com/apk/res/android&#8221;
        android:layout_width=”match_parent”
        android:background=”#ffffff”
        android:layout_height=”match_parent”
        android:orientation=”vertical”>
        
        <com.github.barteksc.pdfviewer.PDFView
        android:id=”@+id/pdfView”
        android:layout_margin=”10dp”
        android:layout_width=”match_parent”
        android:layout_height=”match_parent” />
        </LinearLayout>
        

        PdfActivity.java:

        包 com.pdffilefromsdcard;

        import android.os.Bundle;
        import android.support.annotation.Nullable;
        import android.support.v7.app.AppCompatActivity;
        import android.util.Log;
        
        import com.github.barteksc.pdfviewer.PDFView;
        import com.github.barteksc.pdfviewer.listener.OnLoadCompleteListener;
        import com.github.barteksc.pdfviewer.listener.OnPageChangeListener;
        import com.github.barteksc.pdfviewer.scroll.DefaultScrollHandle;
        import com.shockwave.pdfium.PdfDocument;
        
        import java.io.File;
        import java.util.List;
        
        public class PdfActivity extends AppCompatActivity implements OnPageChangeListener,OnLoadCompleteListener {
        
        PDFView pdfView;
        Integer pageNumber = 0;
        String pdfFileName;
        String TAG=”PdfActivity”;
        int position=-1;
        
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_pdf);
        init();
        }
        
        private void init(){
        pdfView= (PDFView)findViewById(R.id.pdfView);
        position = getIntent().getIntExtra(“position”,-1);
        displayFromSdcard();
        }
        
        private void displayFromSdcard() {
        pdfFileName = MainActivity.fileList.get(position).getName();
        
        pdfView.fromFile(MainActivity.fileList.get(position))
        .defaultPage(pageNumber)
        .enableSwipe(true)
        
        .swipeHorizontal(false)
        .onPageChange(this)
        .enableAnnotationRendering(true)
        .onLoad(this)
        .scrollHandle(new DefaultScrollHandle(this))
        .load();
        }
        @Override
        public void onPageChanged(int page, int pageCount) {
        pageNumber = page;
        setTitle(String.format(“%s %s / %s”, pdfFileName, page + 1, pageCount));
        }
        @Override
        public void loadComplete(int nbPages) {
        PdfDocument.Meta meta = pdfView.getDocumentMeta();
        printBookmarksTree(pdfView.getTableOfContents(), “-“);
        
        }
        
        public void printBookmarksTree(List<PdfDocument.Bookmark> tree, String sep) {
        for (PdfDocument.Bookmark b : tree) {
        
        Log.e(TAG, String.format(“%s %s, p %d”, sep, b.getTitle(), b.getPageIdx()));
        
        if (b.hasChildren()) {
        printBookmarksTree(b.getChildren(), sep + “-“);
        }
        }
        }
        }
        

        谢谢!

        【讨论】:

          【解决方案5】:

          试试这个代码,显示来自/sdcard的pdf文件

          File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"/example.pdf");
          Intent intent = new Intent(Intent.ACTION_VIEW);
          intent.setDataAndType(Uri.fromFile(file), "application/pdf");
          intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
          startActivity(intent);
          

          【讨论】:

          • 感谢您结束我的搜索。为什么这有效,而不是从字符串解析 url?
          • 我怎样才能转到直接特定页面?有什么办法吗?
          • @PratikButani - 当您使用第三方 pdf 应用程序打开 pdf 文件时,您无法处理任何特定页面的 pdf 页面导航。
          • 是的,你是对的,但是如果我想使用内置查看器呢? @user370305
          • 这里的 FLAG_ACTIVITY_NO_HISTORY 信息:developer.android.com/reference/android/content/…
          【解决方案6】:

          这可能与资产文件夹中的文件被压缩有关。

          尝试将其移至您的 res/raw/ 文件夹。

          更多信息:https://stackoverflow.com/a/4432804/413127

          【讨论】:

          • 我什至不再尝试查看我的应用程序的 pdf。我使用我的操作系统将 pdf 复制到 sdcard,但我仍然无法通过 Intent 查看它
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-12-02
          • 1970-01-01
          • 1970-01-01
          • 2012-09-17
          相关资源
          最近更新 更多