如何通过 Intent 从 SD 卡打开 PDF
Posted
技术标签:
【中文标题】如何通过 Intent 从 SD 卡打开 PDF【英文标题】:How to open a PDF via Intent from SD card 【发布时间】: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 查看应用手动打开文档。任何帮助将不胜感激。
【问题讨论】:
【参考方案1】:对于 android Nougat 及更高版本,必须完成更多工作,否则应用将无法打开 .pdf
文件。我们必须使用FileProvider
为URI
设置一个临时权限:
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”
xmlns:tools=”http://schemas.android.com/tools”
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”
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://***.com/a/4432804/413127
【讨论】:
我什至不再尝试查看我的应用程序的 pdf。我使用我的操作系统将 pdf 复制到 sdcard,但我仍然无法通过 Intent 查看它以上是关于如何通过 Intent 从 SD 卡打开 PDF的主要内容,如果未能解决你的问题,请参考以下文章
Android:如何通过 Intent 打开特定文件夹并在文件浏览器中显示其内容?