以编程方式打开pdf文件

时间:2012-07-09 15:28:24

标签: android

我正在研究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();
        }
    }

当我在模拟器中尝试此代码时,它显示一个吐司说“找不到应用程序”(bcoz,通常没有在模拟器中安装pdf查看应用程序)。当我在设备中测试相同的东西时(特别是在funbook选项卡和sony选项卡中),它既没有显示Toast消息也没有打开pdf文件。任何人都可以指出我的代码中的错误。其实我是第一次使用pdf。所以我的问题是,

  1. 在设备中它没有显示toast消息,这意味着有一个 pdf查看手机中安装的应用程序?是不是?
  2. 如果是这样,为什么不使用第三方应用程序打开pdf。
  3. 如果我想列出我所安装的所有pdf查看应用程序 给用户打电话,我应该在这段代码中做些什么改变?

7 个答案:

答案 0 :(得分:3)

尝试使用LuxuryMode的方法:https://stackoverflow.com/a/8221594/1500067

我认为你刚刚错过了adobe包的intent.setPackage(“com.adobe.reader”);

答案 1 :(得分:3)

对于android 9 and 10,您应该使用此代码

1-创建一个class

public class GenericFileProvider extends FileProvider {

}

2在res目录中创建一个目录,名称为xml 并创建一个文件名为provider_paths.xml并添加此代码

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

manifests的{​​{1}}中的3中添加此代码

application

4-您应该获得权限 <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>

5-并添加此代码

Manifest.permission.READ_EXTERNAL_STORAGE

6-我建议您将此代码添加到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")); 中的application

manifests

答案 2 :(得分:2)

我有几乎相同的代码可以正常工作,但我没有在我的应用程序中从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();
}

所以你的方法是正确的。确保您可以先打开文件...即使用mActivity.openFileInput()以确保您具有可读的PDF。

答案 3 :(得分:2)

答案 4 :(得分:1)

我得到了上述问题的解决方案,所以请尝试一次;

步骤: -

  1. 在应用名称下的src中创建资源文件夹。

  2. 在此资源文件夹中保留您的pdf文件,例如schedule1.pdf。

  3. 现在开始你的活动,即MainActivity.java

  4. 任何UI组件上的setListener都是您想要的,(ButtonImageViewImageButton);

  5. 在此侦听器中调用一个用户定义的方法,即openPDFFiles()

  6. 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);
    }
    }
    

答案 5 :(得分:0)

在此处下载源代码(Display PDF file inside my android application

在Gradle文件中添加此依赖项:

compile 'com.github.barteksc:android-pdf-viewer:2.0.3'

<强> activity_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

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

}

答案 6 :(得分:0)

我知道答案可能为时已晚,但是您的问题是由以下两行引起的: intent.setData(path); intent.setType("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;
}

Javadoc Intent class