简体   繁体   English

以编程方式打开一个pdf文件

[英]open a pdf file programmatically

I am working on pdf.我正在处理 pdf。 I am trying to open a pdf file from my application using the code below.我正在尝试使用以下代码从我的应用程序中打开 pdf 文件。 But I failed to open.但是我打不开。

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).当我在模拟器中尝试这段代码时,它显示一个吐司说“找不到应用程序”(bcoz,通常模拟器中没有安装pdf查看应用程序)。 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.当我在设备(特别是在 funbook 选项卡和 sony 选项卡中)测试相同的东西时,它既没有显示 Toast 消息,也没有打开 pdf 文件。 Can anybody point out the mistake in my code.任何人都可以指出我的代码中的错误。 Actually I am working with pdf for the first time.其实我是第一次使用pdf。 So my question is,所以我的问题是,

  1. In device it didn't showed the toast message, which means there is a pdf viewing application installed in my phone?在设备中它没有显示 toast 消息,这意味着我的手机中安装了 pdf 查看应用程序? is it right?这样对吗?
  2. If so, why the pdf is not opened using third party application.如果是这样,为什么不使用第三方应用程序打开 pdf。
  3. If I want to list all pdf viewing applications installed in my phone to the user, what changes should I make in this code?如果我想向用户列出我手机中安装的所有 pdf 查看应用程序,我应该在此代码中进行哪些更改?

I got solution of above problem, so try once;我得到了上述问题的解决方案,所以尝试一次;

Steps:-脚步:-

  1. create assets folder in src under your app name.在您的应用程序名称下的 src 中创建资产文件夹。

  2. In this assets folder keep your pdf files eg schedule1.pdf.在这个资产文件夹中保存您的 pdf 文件,例如 schedule1.pdf。

  3. now come your activity ie MainActivity.java现在来你的活动,即 MainActivity.java

  4. setListener on any UI component what you want ie ( Button , ImageView , ImageButton ); setListener 在任何 UI 组件上你想要什么,即( ButtonImageViewImageButton );

  5. In this listener call one user defined method ie openPDFFiles()在此侦听器中调用一个用户定义的方法,即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);
    }
}

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");

for android 9 and 10 you should use this code对于android 9 and 10您应该使用此代码

1-create one class 1-创建一个class

public class GenericFileProvider extends FileProvider {

}

2-in res directory create one directory to name of xml and create one file to name of provider_paths.xml and add this code 2-in res目录创建一个以xml命名的目录并创建一个以provider_paths.xml命名的文件并添加此代码

<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="external_files" path="."/>
</paths>

3-in manifests in application add this code application 3-in manifests添加此代码

  <provider
    android:name=".Model.Utilitys.GenericFileProvider"
    android:authorities="${applicationId}.provider"
    android:exported="false"
    android:grantUriPermissions="true">
      <meta-data
         android:name="android.support.FILE_PROVIDER_PATHS"
         android:resource="@xml/provider_paths"/>
  </provider>

4-you should get Permission Manifest.permission.READ_EXTERNAL_STORAGE 4-你应该得到 Permission Manifest.permission.READ_EXTERNAL_STORAGE

5-and add this codes 5-并添加此代码

String fileName="yourfile.pdf";

File file = new File(Environment.getExternalStorageDirectory()+"/Android/data/ir.tdaapp.paymanyar/files/File",fileName);

String extension = MimeTypeMap.getFileExtensionFromUrl(Uri.fromFile(file).toString());

String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);

Intent intent = new Intent(Intent.ACTION_VIEW);

intent.setFlags(FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_NEW_TASK);

Uri uri = FileProvider.getUriForFile(getContext(), getActivity().getApplicationContext().getPackageName() + ".provider", file);

intent.setDataAndType(uri, mimeType);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

startActivity(Intent.createChooser(intent, "choseFile"));

6-I suggest you add this code to the application in manifests 6-我建议您将此代码添加到manifestsapplication

android:requestLegacyExternalStorage="true"

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 ... ie use mActivity.openFileInput() to ensure you have a readable PDF.确保您可以先打开文件……即使用 mActivity.openFileInput() 确保您拥有可读的 PDF。

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 + "-");
            }
        }
    }

}

I know maybe is too late for an answer, but your problem is cause by these 2 line: intent.setData(path);我知道答案可能为时已晚,但您的问题是由以下两行引起的: 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.当你 setData 然后你 setType 时,第二个命令将清理 setData 中的路径。 In this situation, you should use setDataAndType(path,"application/pdf")在这种情况下,您应该使用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; }

Javadoc Intent class Javadoc 意图类

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM