无法在应用程序中打开PDF

时间:2018-03-05 11:19:31

标签: android pdf

这是我之前quesion.的延续,我想在应用中打开pdf,而不是使用第三方应用打开它。我重写了代码,以便assets文件夹中的pdf文件可以复制到SD卡中 这是我的代码:

package com.dell.pdfreader;

import android.Manifest;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.AssetManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;

import net.sf.andpdf.pdfviewer.PdfViewerActivity;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class PdfMainActivity extends AppCompatActivity implements View.OnClickListener {

    private static String TAG = PdfMainActivity.class.getCanonicalName();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_pdf_main);

        Button click = (Button) findViewById(R.id.click);
        click.setOnClickListener(this);

    }

    @Override
    public void onClick(View view) {
        Context mContext = getApplicationContext();
        switch (view.getId()) {
            case R.id.click:
                try {

                    AssetManager assetManager = getAssets();
                    String[] files = null;
                    try {
                        files = assetManager.list("pdffiles");
                    } catch (IOException e) {
                        Log.e(TAG, e.getMessage());
                    }

                    for (String fileName : files != null ? files : new String[0]) {
                        InputStream is = null;
                        OutputStream os = null;

                        try {
                            is = assetManager.open("pdffiles/" + fileName);
                            os = new FileOutputStream(Environment.getExternalStorageDirectory().toString() + "/" + fileName);
                            copyFile(is, os);
                            is.close();
                            os.flush();
                            os.close();
                        } catch (Exception e) {
                            Log.e(TAG, e.getMessage());
                        }
                    }

                    Uri path = Uri.parse(Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "Dojo_lab_tour.pdf");
                    String oPath = path.toString();
                    Intent intent = new Intent(PdfMainActivity.this, ReaderActivity.class);
                    if (ContextCompat.checkSelfPermission(PdfMainActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
                        intent.setDataAndType(path, "application/pdf");
                        intent.putExtra(PdfViewerActivity.EXTRA_PDFFILENAME, oPath);
                        startActivity(intent);
                    } else {
                        Log.d(TAG, "No permission!");
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
        }
    }

    private void copyFile(InputStream is, OutputStream os) throws IOException {
        byte[] buffer = new byte[1024];
        int read;
        while ((read = is.read(buffer)) != -1) {
            os.write(buffer, 0, read);
        }
    }
}  

这是我的第二项活动:

package com.dell.pdfreader;

import android.os.Bundle;

public class ReaderActivity extends net.sf.andpdf.pdfviewer.PdfViewerActivity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_reader);
    }

    @Override
    public int getPreviousPageImageResource() {
        return R.drawable.left_arrow;
    }

    @Override
    public int getNextPageImageResource() {
        return R.drawable.right_arrow;
    }

    @Override
    public int getZoomInImageResource() {
        return R.drawable.zoom_in;
    }

    @Override
    public int getZoomOutImageResource() {
        return R.drawable.zoom_out;
    }

    @Override
    public int getPdfPasswordLayoutResource() {
        return 0;
    }

    @Override
    public int getPdfPageNumberResource() {
        return 0;
    }

    @Override
    public int getPdfPasswordEditField() {
        return 0;
    }

    @Override
    public int getPdfPasswordOkButton() {
        return 0;
    }

    @Override
    public int getPdfPasswordExitButton() {
        return 0;
    }

    @Override
    public int getPdfPageNumberEditField() {
        return 0;
    }
}  

当我运行该代码时,我收到此错误:

03-05 16:19:43.000 14997-14997/com.dell.pdfreader E/com.dell.pdfreader.PdfMainActivity: /storage/emulated/0/Dojo_Lab_Tour.pdf (Permission denied)
03-05 16:19:43.049 14997-14997/com.dell.pdfreader I/PDFVIEWER: onCreate
03-05 16:19:43.049 14997-14997/com.dell.pdfreader E/PDFVIEWER: restoreInstance
03-05 16:19:43.119 14997-14997/com.dell.pdfreader I/PDFVIEWER: Intent { dat=/storage/emulated/0/Dojo_lab_tour.pdf typ=application/pdf cmp=com.dell.pdfreader/.ReaderActivity (has extras) }
03-05 16:19:43.124 14997-14997/com.dell.pdfreader I/PDFVIEWER: ST='file '/storage/emulated/0/Dojo_lab_tour.pdf' not found'  

mainfest文件中,我添加了以下两行:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>  

如何解决此错误?
修改
我的资产文件夹结构如下:
assets folder
我根据Tommin和Commonsware的建议修改了我的代码:

if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
                        Intent intent = new Intent(PdfMainActivity.this, ReaderActivity.class);
                        if (checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
                            intent.setDataAndType(path, "application/pdf");
                            intent.putExtra(PdfViewerActivity.EXTRA_PDFFILENAME, oPath);
                            startActivity(intent);
                        } else {
                            Log.d(TAG, "No permission!");
                        }
                    }  

立即收到此错误:

03-05 17:45:26.526 7888-7888/com.dell.pdfreader E/com.dell.pdfreader.PdfMainActivity: /storage/emulated/0/Dojo_Lab_Tour.pdf (Permission denied)  

2 个答案:

答案 0 :(得分:2)

1-在您的清单中添加权限,就像您一样:

<manifest 
    xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.....">

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

2-这两个权限被认为是危险权限,您应该在运行时请求onClick on on on方法:

@Override
public void onClick (View view) {
    if (ContextCompat.checkSelfPermission (PdfMainActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED ||
            ContextCompat.checkSelfPermission (PdfMainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {

        ActivityCompat.requestPermissions (PdfMainActivity.this, new String [] { Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE }, 1000);
        return;
    }
    ...
}

3-在将流复制到其中之前,确保外部存储器是可写的:

if (!isExternalStorageWritable ()) {
    throw new Exception ("External Storage Not Writable");
}

private boolean isExternalStorageWritable () {
    return Environment.MEDIA_MOUNTED.equals (Environment.getExternalStorageState ());
}

4-您的代码变为:

@Override
public void onClick (View v) {
    if (ContextCompat.checkSelfPermission (PdfMainActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED ||
            ContextCompat.checkSelfPermission (PdfMainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {

        ActivityCompat.requestPermissions (PdfMainActivity.this, new String [] { Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE }, 1000);
        return;
    }

    AssetManager assetManager = getAssets ();

    String dir = "pdffiles";

    try {
        String [] paths = assetManager.list (dir);
        for (String path : paths) {
            if (!isExternalStorageWritable ()) {
                throw new Exception ("External Storage Not Writable");
            }

            InputStream is  = assetManager.open (dir + File.separator + path);
            OutputStream os = new FileOutputStream (Environment.getExternalStorageDirectory () + File.separator + path);

            copy (is, os);

            closeQuietly (os, is);
        }
    } catch (Exception e) {
        // TODO Catch your exception here
    }
}

public static int copy (InputStream is, OutputStream os) throws IOException {
    long count = 0;
    int n;

    byte [] buffer = new byte [4 * 1024];

    while (-1 != (n = is.read (buffer))) {
        os.write (buffer, 0, n);
        count += n;
    }

    if (count > Integer.MAX_VALUE) {
        return -1;
    }

    return (int) count;
}

public static void closeQuietly (Closeable... closeables) {
    if (closeables == null || closeables.length == 0) {
        return;
    }
    try {
        for (Closeable closeable : closeables) {
            if (closeable != null) {
                closeable.close ();
            }
        }
    } catch (final IOException ignore) { }
}

5-尝试阅读PDF时,请确保外部存储器也可以通过以下方式读取:

private boolean isExternalStorageReadable() {
    String state = Environment.getExternalStorageState ();
    return Environment.MEDIA_MOUNTED.equals (state) || Environment.MEDIA_MOUNTED_READ_ONLY.equals (state);
}

6-将复制处理放在后台线程上,不要阻止UI。并且可能向用户显示进度弹出窗口。

答案 1 :(得分:0)

我明白了,伙计们。我修改了我的代码:

Uri path = Uri.parse(Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "EPSF.pdf");
                    String oPath = path.toString();
                    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
                        if (checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED
                                && checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED ) {
                            ActivityCompat.requestPermissions(PdfMainActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE}, 1000);
                            Log.d(TAG, "No permission!");
                        } else {
                            Intent intent1 = new Intent(PdfMainActivity.this, ReaderActivity.class);
                            intent1.setDataAndType(path, "application/pdf");
                            intent1.putExtra(PdfViewerActivity.EXTRA_PDFFILENAME, oPath);
                            startActivity(intent1);
                        }
                    }  

我添加了运行时权限,并根据Mehdi的建议进行了修改。