Android 以编程方式打开一个pdf文件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11398239/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
open a pdf file programmatically
提问by Sanal Varghese
I am working on pdf. I am trying to open a pdf file from my application using the code below. But I failed to open.
我正在处理 pdf。我正在尝试使用以下代码从我的应用程序中打开 pdf 文件。但是我打不开。
private void openPdf() {
File file = new File("mnt/sdcard.test.pdf");
Uri path = Uri.fromFile(file);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.setAction(Intent.ACTION_VIEW);
intent.setData(path);
intent.setType("application/pdf");
try {
startActivity(intent);
} catch (ActivityNotFoundException e) {
Toast.makeText(getActivity(), "No application found",
Toast.LENGTH_SHORT).show();
}
}
When I tried this code in emulator,it shows a toast saying "No application found"(bcoz,normally no pdf viewing application are installed in emulator). When I tested the same thing in device (specifically in funbook tab and in sony tab), it neither showed the Toast message nor it opened the pdf file. Can anybody point out the mistake in my code. Actually I am working with pdf for the first time. So my question is,
当我在模拟器中尝试这段代码时,它显示一个吐司说“找不到应用程序”(bcoz,通常模拟器中没有安装pdf查看应用程序)。当我在设备(特别是在 funbook 选项卡和 sony 选项卡中)测试相同的东西时,它既没有显示 Toast 消息,也没有打开 pdf 文件。任何人都可以指出我的代码中的错误。其实我是第一次使用pdf。所以我的问题是,
- In device it didn't showed the toast message, which means there is a pdf viewing application installed in my phone? is it right?
- If so, why the pdf is not opened using third party application.
- If I want to list all pdf viewing applications installed in my phone to the user, what changes should I make in this code?
- 在设备中它没有显示 toast 消息,这意味着我的手机中安装了 pdf 查看应用程序?这样对吗?
- 如果是这样,为什么不使用第三方应用程序打开 pdf。
- 如果我想向用户列出我手机中安装的所有 pdf 查看应用程序,我应该在此代码中进行哪些更改?
回答by firefistace
Try LuxuryMode's method: https://stackoverflow.com/a/8221594/1500067
试试 LuxuryMode 的方法:https://stackoverflow.com/a/8221594/1500067
I think your just missing the adobe package intent.setPackage("com.adobe.reader");
我认为您只是缺少 adobe 包 intent.setPackage("com.adobe.reader");
回答by CSmith
I have nearly identical code that works fine, though I'm not opening a file from SD card in my app.
我有几乎相同的代码可以正常工作,但我没有在我的应用程序中打开 SD 卡中的文件。
Activity mActivity = /* your activity */...;
String mFileName = /* path of my PDF file */...;
Uri uri = Uri.fromFile(mActivity.getFileStreamPath(mFileName));
try
{
Intent intentUrl = new Intent(Intent.ACTION_VIEW);
intentUrl.setDataAndType(uri, "application/pdf");
intentUrl.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
mActivity.startActivity(intentUrl);
}
catch (ActivityNotFoundException e)
{
Toast.makeText(mActivity, "No PDF Viewer Installed", Toast.LENGTH_LONG).show();
}
so your approach is right on. Make sure you can open the file first ... i.e. use mActivity.openFileInput() to ensure you have a readable PDF.
所以你的方法是正确的。确保您可以先打开文件……即使用 mActivity.openFileInput() 确保您拥有可读的 PDF。
回答by sachin pangare
I got solution of above problem, so try once;
我得到了上述问题的解决方案,所以尝试一次;
Steps:-
脚步:-
create assets folder in src under your app name.
In this assets folder keep your pdf files e.g. schedule1.pdf.
now come your activity i.e MainActivity.java
setListener on any UI component what you want i.e (
Button
,ImageView
,ImageButton
);In this listener call one user defined method i.e.
openPDFFiles()
在您的应用程序名称下的 src 中创建资产文件夹。
在这个资产文件夹中保存您的 pdf 文件,例如 schedule1.pdf。
现在来你的活动,即 MainActivity.java
setListener 在任何 UI 组件上你想要什么,即 (
Button
,ImageView
,ImageButton
);在此侦听器中调用一个用户定义的方法,即
openPDFFiles()
the openPDFFiles() method have below code:
openPDFFiles() 方法具有以下代码:
private void openPDFFiles() {
AssetManager assetManager = getAssets();
InputStream in = null;
OutputStream out = null;
File file = new File(getFilesDir(), “schedule1.pdf”);//here schedule1.pdf is the pdf file name which is keep in assets folder.
try {
in = assetManager.open(“schedule1.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());
}
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.parse(“file://” + getFilesDir() + “/schedule1.pdf”), “application/pdf”);
startActivity(intent);
}
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);
}
}
回答by paxbat14
You can achieve this using 3rd party library integration. Working libraries are listed below, with SDK
您可以使用 3rd 方库集成来实现这一点。下面列出了工作库,带有 SDK
https://github.com/JoanZapata/android-pdfview
https://github.com/jblough/Android-Pdf-Viewer-Library
https://github.com/JoanZapata/android-pdfview
https://github.com/jblough/Android-Pdf-Viewer-Library
with NDK
使用 NDK
https://code.google.com/p/mupdf/downloads/detail?name=mupdf-1.2-source.zip&can=2&q=
https://code.google.com/p/mupdf/downloads/detail?name=mupdf-1.2-source.zip&can=2&q=
guide to use @
使用指南@
http://dixitpatel.com/integrating-pdf-in-android-application/
http://dixitpatel.com/integrating-pdf-in-android-application/
回答by Deepshikha Puri
Download the source code here(Display PDF file inside my android application)
在此处下载源代码(在我的 android 应用程序中显示 PDF 文件)
Add this dependency in your Gradle file:
在您的 Gradle 文件中添加此依赖项:
compile 'com.github.barteksc:android-pdf-viewer:2.0.3'
activity_main.xml
活动_main.xml
<RelativeLayout android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffff"
xmlns:android="http://schemas.android.com/apk/res/android" >
<TextView
android:layout_width="match_parent"
android:layout_height="40dp"
android:background="@color/colorPrimaryDark"
android:text="View PDF"
android:textColor="#ffffff"
android:id="@+id/tv_header"
android:textSize="18dp"
android:gravity="center"></TextView>
<com.github.barteksc.pdfviewer.PDFView
android:id="@+id/pdfView"
android:layout_below="@+id/tv_header"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
MainActivity.java
主活动.java
import android.app.Activity;
import android.database.Cursor;
import android.net.Uri;
import android.provider.OpenableColumns;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.RelativeLayout;
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.util.List;
public class MainActivity extends Activity implements OnPageChangeListener,OnLoadCompleteListener{
private static final String TAG = MainActivity.class.getSimpleName();
public static final String SAMPLE_FILE = "android_tutorial.pdf";
PDFView pdfView;
Integer pageNumber = 0;
String pdfFileName;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
pdfView= (PDFView)findViewById(R.id.pdfView);
displayFromAsset(SAMPLE_FILE);
}
private void displayFromAsset(String assetFileName) {
pdfFileName = assetFileName;
pdfView.fromAsset(SAMPLE_FILE)
.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 + "-");
}
}
}
}
回答by Daniel Luche
I know maybe is too late for an answer, but your problem is cause by these 2 line:
intent.setData(path);
intent.setType("application/pdf");
我知道答案可能为时已晚,但您的问题是由以下 2 行引起的:
intent.setData(path);
intent.setType("application/pdf");
When you setData and after that you setType, the second command will clean the path assingned in setData.
In this situation, you should use setDataAndType(path,"application/pdf")
当你 setData 然后你 setType 时,第二个命令将清理 setData 中的路径。在这种情况下,您应该使用setDataAndType(path,"application/pdf")
/** * Set an explicit MIME data type. * * <p>This is used to create intents that only specify a type and not data, * for example to indicate the type of data to return. * * <p>This method automatically clears any data that was * previously set (for example by {@link #setData}). * * <p><em>Note: MIME type matching in the Android framework is * case-sensitive, unlike formal RFC MIME types. As a result, * you should always write your MIME types with lower case letters, * or use {@link #normalizeMimeType} or {@link #setTypeAndNormalize} * to ensure that it is converted to lower case.</em> * * @param type The MIME type of the data being handled by this intent. * * @return Returns the same Intent object, for chaining multiple calls * into a single statement. * * @see #getType * @see #setTypeAndNormalize * @see #setDataAndType * @see #normalizeMimeType */ public Intent setType(String type) { mData = null; mType = type; return this; }
/** * Set an explicit MIME data type. * * <p>This is used to create intents that only specify a type and not data, * for example to indicate the type of data to return. * * <p>This method automatically clears any data that was * previously set (for example by {@link #setData}). * * <p><em>Note: MIME type matching in the Android framework is * case-sensitive, unlike formal RFC MIME types. As a result, * you should always write your MIME types with lower case letters, * or use {@link #normalizeMimeType} or {@link #setTypeAndNormalize} * to ensure that it is converted to lower case.</em> * * @param type The MIME type of the data being handled by this intent. * * @return Returns the same Intent object, for chaining multiple calls * into a single statement. * * @see #getType * @see #setTypeAndNormalize * @see #setDataAndType * @see #normalizeMimeType */ public Intent setType(String type) { mData = null; mType = type; return this; }