27
public void DOCS(View btnDocs)
{   
    File fileBrochure = new File("android.resource://com.project.datastructure/assets/abc.pdf");
    if (!fileBrochure.exists())
    {
         CopyAssetsbrochure();
    } 

    /** PDF reader code */
    File file = new File("android.resource://com.project.datastructure/assets/abc.pdf");        

    Intent intent = new Intent(Intent.ACTION_VIEW);
    intent.setDataAndType(Uri.fromFile(file),"application/pdf");
    intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    try 
    {
        getApplicationContext().startActivity(intent);
    } 
    catch (ActivityNotFoundException e) 
    {
         Toast.makeText(Stack_dr.this, "NO Pdf Viewer", Toast.LENGTH_SHORT).show();
    }
}
private void CopyAssetsbrochure() {
    AssetManager assetManager = getAssets();
    String[] files = null;
    try 
    {
        files = assetManager.list("");
    } 
    catch (IOException e){}
    for(int i=0; i<files.length; i++)
    {
        String fStr = files[i];
        if(fStr.equalsIgnoreCase("abc.pdf"))
        {
            InputStream in = null;
            OutputStream out = null;
            try 
            {
              in = assetManager.open(files[i]);
              out = new FileOutputStream("/sdcard/" + files[i]);
              copyFile(in, out);
              in.close();
              in = null;
              out.flush();
              out.close();
              out = null;
              break;
            } 
            catch(Exception e){}
        }
    }
}

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

我正在尝试从我的应用程序文件夹中的 assets 文件夹中读取一个 pdf 文件。当我单击我的 DOCS 按钮时,一切正常,弹出一个窗口让我选择一个打开 pdf 的应用程序,即“abc.pdf”,但在选择一个选项后,我收到一条错误消息“文件路径无效”。我认为它们与我在代码中指定的路径存在一些问题。请帮忙

4

11 回答 11

37

尝试这个

public class SampleActivity extends Activity
    {

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

        }

        private void CopyReadAssets()
        {
            AssetManager assetManager = getAssets();

            InputStream in = null;
            OutputStream out = null;
            File file = new File(getFilesDir(), "abc.pdf");
            try
            {
                in = assetManager.open("abc.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() + "/abc.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);
            }
        }

    }

确保包括

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

在清单中

于 2013-06-13T11:17:41.357 回答
14

你可以这样做(测试并使用 API 27)

步骤1

在您的应用程序 gradle 中添加以下依赖项:

implementation 'com.github.barteksc:android-pdf-viewer:2.8.2'

第2步

添加以下 XML 代码:

<com.github.barteksc.pdfviewer.PDFView
         android:id="@+id/pdfv"
         android:layout_width="match_parent"
         android:layout_height="match_parent"> 
</com.github.barteksc.pdfviewer.PDFView>

第 3 步

在您的 java 文件中添加以下代码:

public class MainActivity extends AppCompatActivity {

    PDFView pdfView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        pdfView=findViewById(R.id.pdfv);
        pdfView.fromAsset("filename.pdf").load();
    }
}

这些更改将在您创建活动时加载 PDF 文件。

于 2018-06-23T13:09:51.703 回答
6

虽然已经回答了这个问题,但我想分享我的解决方案,因为我认为它更容易包含在内。

用法:

new OpenLocalPDF(context, 'nameOfPDFStoredInAssets').execute()

这是OpenLocalPDF课程:

public class OpenLocalPDF {

    private static String TAG = OpenLocalPDF.class.getSimpleName();

    private WeakReference<Context> contextWeakReference;
    private String fileName;

    public OpenLocalPDF(Context context, String fileName) {
        this.contextWeakReference = new WeakReference<>(context);
        this.fileName = fileName.endsWith("pdf") ? fileName : fileName + ".pdf";
    }

    public void execute() {

        Context context = contextWeakReference.get();
        if (context != null) {
            new CopyFileAsyncTask().execute();
        }

    }


    private class CopyFileAsyncTask extends AsyncTask<Void, Void, File> {


        final String appDirectoryName = BuildConfig.APPLICATION_ID;
        final File fileRoot = new File(Environment.getExternalStoragePublicDirectory(
                Environment.DIRECTORY_DOCUMENTS), appDirectoryName);

        @Override
        protected File doInBackground(Void... params) {

            Context context = contextWeakReference.get();

            AssetManager assetManager = context.getAssets();

            File file = new File(fileRoot, fileName);

            InputStream in = null;
            OutputStream out = null;
            try {

                file.mkdirs();

                if (file.exists()) {
                    file.delete();
                }

                file.createNewFile();


                in = assetManager.open(fileName);
                Log.d(TAG, "In");

                out = new FileOutputStream(file);
                Log.d(TAG, "Out");

                Log.d(TAG, "Copy file");
                copyFile(in, out);

                Log.d(TAG, "Close");
                in.close();

                out.flush();
                out.close();

                return file;
            } catch (Exception e)
            {
                Log.e(TAG, e.getMessage());
            }

            return null;
        }

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

        @Override
        protected void onPostExecute(File file) {
            super.onPostExecute(file);

            Context context = contextWeakReference.get();


            Intent intent = new Intent(Intent.ACTION_VIEW);
            intent.setDataAndType(
                    Uri.fromFile(file),
                    "application/pdf");

            context.startActivity(intent);

        }
    }
}

将此权限添加到Manifest.xml

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
于 2016-12-18T20:47:01.120 回答
3

就像说sunsil,但在外部目录的情况下。

import android.app.Activity;
import android.content.Intent;
import android.content.res.AssetManager;
import android.net.Uri;
import android.os.Environment;
import android.os.Bundle;
import android.util.Log;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;


public class MainActivity extends Activity {

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

        copyReadAssets();
    }


    private void copyReadAssets()
    {
        AssetManager assetManager = getAssets();

        InputStream in = null;
        OutputStream out = null;

        String strDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)+ File.separator + "Pdfs";
        File fileDir = new File(strDir);
        fileDir.mkdirs();   // crear la ruta si no existe
        File file = new File(fileDir, "example2.pdf");



        try
        {

            in = assetManager.open("example.pdf");  //leer el archivo de assets
            out = new BufferedOutputStream(new FileOutputStream(file)); //crear el archivo


            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://" + Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + File.separator + "Pdfs" + "/example2.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);
        }
    }
}

更改部分代码,如下所示:

out = new BufferedOutputStream(new FileOutputStream(file));

前面的示例是针对 Pdfs 的,如果是示例 .txt

FileOutputStream fos = new FileOutputStream(file);
于 2015-05-28T21:43:56.093 回答
1

我使用来自cYrixmorten的答案和OpenLocalPDF类取得了成功。

但是,Android 18 不支持 Environment.DIRECTORY_DOCUMENTS。为了支持 Android 18 - 28,我必须进行以下更改。

在“CopyFileAsyncTask”中,更改 fileRoot 声明:

final File fileRoot = new File(Environment.getExternalStoragePublicDirectory(
        Environment.DIRECTORY_DOCUMENTS), appDirectoryName);

对此:

final File fileRoot = new File(Environment.getExternalStorageDirectory() + "/YourAppName");

在“onPostExecute”中,改变这个:

Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(
        Uri.fromFile(file),
        "application/pdf");
context.startActivity(intent);

对此:

Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(FileProvider.getUriForFile(context, "com.example.yourappname.provider", file), "application/pdf");
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
context.startActivity(intent);

最后,按照本文所述设置清单以支持FileProvider

于 2019-07-07T20:02:11.413 回答
1

这对我有用。

第 1 步:在 MainActivity.java

public class SampleActivity extends Activity  {

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

    //call this method by passing file name in params.
    readFromAssets("User guide.pdf");
 }

public static void readFromAssets(String fileName) {
    AssetManager assetManager = getAssets();
    InputStream in = null;
    OutputStream out = null;
    File file = new File(mContext.getFilesDir(), fileName);
    try {
        in = assetManager.open(fileName);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            out = mContext.openFileOutput(file.getName(), Context.MODE_PRIVATE);
        } else {
            out = mContext.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());
    }
    Uri pdfFileURI;
    Intent intent = new Intent(Intent.ACTION_VIEW);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        pdfFileURI = FileProvider.getUriForFile(mContext,
                BuildConfig.APPLICATION_ID + ".provider", file);
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    } else {
        pdfFileURI = Uri.parse("file://" + mContext.getFilesDir() + "/" + fileName);
    }
    intent.setDataAndType(pdfFileURI, "application/pdf");
    mContext.startActivity(intent);
 }

   private static 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);
     }
   }
}

第 2 步:provider_paths.xml在内部创建res->xml->provider_paths.xml. 看这里

<?xml version="1.0" encoding="utf-8"?>
<paths>
  <external-path
    name="external"
    path="." />
  <root-path
    name="root"
    path="." />
</paths>

第 3 步:在 AndroidManifest.xml 中

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

<application
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppThemeMaterial">

  <!-- INSIDE APPLICATION TAG -->

  <provider
        android:name="androidx.core.content.FileProvider"
        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>
</application>     
于 2020-04-21T08:00:06.740 回答
1

尝试通过资产文件夹中的意图(在我的情况下为 PDF)打开文件时,没有开箱即用的答案。所以这是我的解决方案,结合了 2 个出色的答案,我相信它会对某人有所帮助。必须为 api >= 24。

一旦你点击了这个链接并添加了你自己的并在标签GenericFileProvider内的清单中声明它并创建了简单的使用下面的类并调用它:Applicationprovider_paths.xml

OpenLocalPDF(this, "YOUR_PDF_NAME_IN_ASSETS_FOLDER.pdf").execute()

OpenLocalPdf.kt :(也感谢 OP https://stackoverflow.com/a/41212708/1133011

import android.content.Context
import android.content.Intent
import android.content.res.AssetManager
import android.os.AsyncTask
import android.util.Log
import androidx.core.content.FileProvider
import java.io.File
import java.io.FileOutputStream
import java.io.InputStream
import java.io.OutputStream
import java.lang.ref.WeakReference

class OpenLocalPDF(context: Context?, fileName: String?) {
    private val contextWeakReference: WeakReference<Context?>?
    private val fileName: String?
    fun execute() {
        val context: Context = contextWeakReference!!.get()!!
        if (context != null) {
            CopyFileAsyncTask().execute()
        }
    }

    private inner class CopyFileAsyncTask :
        AsyncTask<Void?, Void?, File?>() {
        val appDirectoryName: String? = co.za.umbiflow.BuildConfig.APPLICATION_ID
        val fileRoot: File? = File(
            android.os.Environment.getExternalStoragePublicDirectory(
                android.os.Environment.DIRECTORY_DOCUMENTS
            ), appDirectoryName
        )

        override fun doInBackground(vararg params: Void?): File? {
            val context: Context = contextWeakReference!!.get()!!
            val assetManager: AssetManager = context.getAssets()
            val file = File(fileRoot, fileName)
            var `in`: InputStream? = null
            var out: OutputStream? = null
            try {
                file.mkdirs()
                if (file.exists()) {
                    file.delete()
                }
                file.createNewFile()
                `in` = assetManager.open(fileName)
                out = FileOutputStream(file)
                copyFile(`in`, out)
                `in`.close()
                out.flush()
                out.close()
                return file
            } catch (e: Exception) {
                Log.e(TAG, e.message)
            }
            return null
        }

        private fun copyFile(`in`: InputStream, out: OutputStream) {
            val buffer = ByteArray(1024)
            var read: Int
            while (`in`.read(buffer).also { read = it } != -1) {
                out.write(buffer, 0, read)
            }
        }

        override fun onPostExecute(file: File?) {
            super.onPostExecute(file)
            val context: Context = contextWeakReference!!.get()!!

            var pdfUri =
                FileProvider.getUriForFile(
                    context,
                    context.packageName + ".provider",
                    file!!
                )

            val intent = Intent()
            intent.action = Intent.ACTION_VIEW
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
            intent.setDataAndType(
                pdfUri,
                "application/pdf"
            )
            context.startActivity(intent)
        }
    }

    companion object {
        private val TAG = OpenLocalPDF::class.java.simpleName
    }

    init {
        contextWeakReference = WeakReference(context)
        this.fileName = if (fileName!!.endsWith("pdf")) fileName else "$fileName.pdf"
    }
}
于 2020-06-21T22:31:35.520 回答
1

这是一种使用 zip 文件从资产中打开多个 PDF 文件的方法。

步骤 1:将 zip 文件 ( pdf.zip) 复制到包含 pdf 列表的 assets 文件夹中

步骤 2:将 PDF 写入应用程序内部的 Utils 类的外部缓存中

public static void writePDFs(Context context) {
        try {
            InputStream inputStream = context.getApplicationContext().getAssets().open("pdf.zip");
            ZipInputStream zipInputStream = new ZipInputStream(inputStream);
            ZipEntry zipEntry;
            File file = new File(context.getExternalCacheDir().getAbsolutePath(), "PDFs");
            if (!file.getAbsoluteFile().exists()) {
                if (file.mkdir()) {
                    BufferedOutputStream outputStream;
                    byte[] buffer = new byte[1024];
                    int count;
                    while ((zipEntry = zipInputStream.getNextEntry()) != null) {
                        String s1 = file + "/" + zipEntry.getName();
                        File file1 = new File(s1);
                        if (!file1.exists()) {
                            file1.createNewFile();
                        }
                        outputStream = new BufferedOutputStream(new FileOutputStream(file1));
                        while ((count = zipInputStream.read(buffer)) != -1) {
                            outputStream.write(buffer, 0, count);
                        }
                        outputStream.flush();
                        outputStream.close();
                        zipInputStream.closeEntry();
                    }
                }
                zipInputStream.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

Step3:在Activities onCreate中调用上述函数

@Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        FileUtils.writePDFs(this);
}

Step4:在Utils类中创建一个打开PDF的常用函数

public static void openPDF(Activity activity, String fileName) {
        if (activity == null) return;
        File file = new File(activity.getExternalCacheDir().getAbsolutePath() + "/PDFs" + "/" + fileName);
        Uri docUri = GenericFileProvider.getUriForFile(activity, activity.getApplicationContext().getPackageName(), file);
        try {
            Intent intent = new Intent();
            intent.setAction(Intent.ACTION_VIEW);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                intent.setDataAndType(docUri, "application/pdf");
            } else {
                intent.setDataAndType(Uri.fromFile(file), "application/pdf");
            }
            activity.startActivityForResult(intent, ACTIVITY_VIEW_ATTACHMENT);
        } catch (ActivityNotFoundException e) {
            e.printStackTrace();
        }
    }

Step5:openPDF在Activity中点击视图调用该函数

myView.setOnClickListener(v -> ApplicationUtils.openPDF(this, "MyPdfFile.pdf"));
于 2021-05-04T08:33:32.430 回答
0

尝试这个:

public String getAssetsPdfPath(Context context) {
String filePath = context.getFilesDir() + File.separator + "myFile.pdf";
File destinationFile = new File(filePath);

try {
FileOutputStream outputStream = new FileOutputStream(destinationFile);
InputStream inputStream = context.getAssets().open("myFile.pdf");
byte[] buffer = new byte[1024];
int length = 0;
while ((length = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, length);
}
outputStream.close();
inputStream.close();
} catch (IOException e) {
Log.e(context.getClass().getSimpleName(), "Error.");
}

return destinationFile.getPath();
}
于 2017-05-15T06:27:12.557 回答
-1

如果您想打开本地存储在 assets 文件夹中的 .pdf 文件而不使用 Intent 来启动外部应用程序,我建议使用 Android 类 PdfRenderer。在此处找到的文档。

是一个对我有用的好例子。

但是,当我下载它时,这个例子不会运行。我不得不对其进行一些更改以使用此处其他答案中提到的 copyReadAssets() 函数,然后引用该文件(在复制后)我使用:

File file = new File("/data/data/" + getContext().getPackageName() + "/files/mypdf.pdf");

我还最终修改了 onAttach(),因为它使用了已弃用的 onAttach() 和 closeRenderer() 形式,因为它会在关闭为空的对象时抛出错误。

所以我完整的 PdfRendererBasicFragment.java 文件看起来像这样:

package com.example.android.pdfrendererbasic;

import android.app.Activity;
import android.app.Fragment;
import android.content.Context;
import android.content.res.AssetManager;
import android.graphics.Bitmap;
import android.graphics.pdf.PdfRenderer;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

/**
 * This fragment has a big {@ImageView} that shows PDF pages, and 2 {@link android.widget.Button}s to move between
 * pages. We use a {@link android.graphics.pdf.PdfRenderer} to render PDF pages as {@link android.graphics.Bitmap}s.
 */
public class PdfRendererBasicFragment extends Fragment implements View.OnClickListener {

    /**
     * Key string for saving the state of current page index.
     */
    private static final String STATE_CURRENT_PAGE_INDEX = "current_page_index";

    /**
     * File descriptor of the PDF.
     */
    private ParcelFileDescriptor mFileDescriptor;

    /**
     * {@link android.graphics.pdf.PdfRenderer} to render the PDF.
     */
    private PdfRenderer mPdfRenderer;

    /**
     * Page that is currently shown on the screen.
     */
    private PdfRenderer.Page mCurrentPage;

    /**
     * {@link android.widget.ImageView} that shows a PDF page as a {@link android.graphics.Bitmap}
     */
    private ImageView mImageView;

    /**
     * {@link android.widget.Button} to move to the previous page.
     */
    private Button mButtonPrevious;

    /**
     * {@link android.widget.Button} to move to the next page.
     */
    private Button mButtonNext;

    public PdfRendererBasicFragment() {
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_pdf_renderer_basic, container, false);
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        // Retain view references.
        mImageView = (ImageView) view.findViewById(R.id.image);
        mButtonPrevious = (Button) view.findViewById(R.id.previous);
        mButtonNext = (Button) view.findViewById(R.id.next);
        // Bind events.
        mButtonPrevious.setOnClickListener(this);
        mButtonNext.setOnClickListener(this);
        // Show the first page by default.
        int index = 0;
        // If there is a savedInstanceState (screen orientations, etc.), we restore the page index.
        if (null != savedInstanceState) {
            index = savedInstanceState.getInt(STATE_CURRENT_PAGE_INDEX, 0);
        }
        showPage(index);
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        try {
            openRenderer(context);
        } catch (IOException e) {
            e.printStackTrace();
            Toast.makeText(context, "Error! " + e.getMessage(), Toast.LENGTH_SHORT).show();
            getActivity().finish();
        }
    }

    @Override
    public void onDetach() {
        try {
            closeRenderer();
        } catch (IOException e) {
            e.printStackTrace();
        }
        super.onDetach();
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        if (null != mCurrentPage) {
            outState.putInt(STATE_CURRENT_PAGE_INDEX, mCurrentPage.getIndex());
        }
    }

    /**
     * Sets up a {@link android.graphics.pdf.PdfRenderer} and related resources.
     */
    private void openRenderer(Context context) throws IOException {
        // Copy the pdf to a usable location
        CopyReadAssets();

        File file = new File("/data/data/" + context.getPackageName() + "/files/sample.pdf");
        mPdfRenderer = new PdfRenderer(ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY));
    }

    /**
     * Closes the {@link android.graphics.pdf.PdfRenderer} and related resources.
     *
     * @throws java.io.IOException When the PDF file cannot be closed.
     */
    private void closeRenderer() throws IOException {
        if (mCurrentPage != null) {
            mCurrentPage.close();
        }

        if (mPdfRenderer != null) {
            mPdfRenderer.close();
        }

        if (mFileDescriptor != null) {
            mFileDescriptor.close();
        }
    }

    /**
     * Shows the specified page of PDF to the screen.
     *
     * @param index The page index.
     */
    private void showPage(int index) {
        if (mPdfRenderer.getPageCount() <= index) {
            return;
        }
        // Make sure to close the current page before opening another one.
        if (null != mCurrentPage) {
            mCurrentPage.close();
        }
        // Use `openPage` to open a specific page in PDF.
        mCurrentPage = mPdfRenderer.openPage(index);
        // Important: the destination bitmap must be ARGB (not RGB).
        Bitmap bitmap = Bitmap.createBitmap(mCurrentPage.getWidth(), mCurrentPage.getHeight(),
                Bitmap.Config.ARGB_8888);
        // Here, we render the page onto the Bitmap.
        // To render a portion of the page, use the second and third parameter. Pass nulls to get
        // the default result.
        // Pass either RENDER_MODE_FOR_DISPLAY or RENDER_MODE_FOR_PRINT for the last parameter.
        mCurrentPage.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY);
        // We are ready to show the Bitmap to user.
        mImageView.setImageBitmap(bitmap);
        updateUi();
    }

    /**
     * Updates the state of 2 control buttons in response to the current page index.
     */
    private void updateUi() {
        int index = mCurrentPage.getIndex();
        int pageCount = mPdfRenderer.getPageCount();
        mButtonPrevious.setEnabled(0 != index);
        mButtonNext.setEnabled(index + 1 < pageCount);
        getActivity().setTitle(getString(R.string.app_name_with_index, index + 1, pageCount));
    }

    /**
     * Gets the number of pages in the PDF. This method is marked as public for testing.
     *
     * @return The number of pages.
     */
    public int getPageCount() {
        return mPdfRenderer.getPageCount();
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.previous: {
                // Move to the previous page
                showPage(mCurrentPage.getIndex() - 1);
                break;
            }
            case R.id.next: {
                // Move to the next page
                showPage(mCurrentPage.getIndex() + 1);
                break;
            }
        }
    }

    private void CopyReadAssets()
    {
        AssetManager assetManager = getActivity().getAssets();

        InputStream in = null;
        OutputStream out = null;
        File file = new File(getActivity().getFilesDir(), "sample.pdf");

        if(!file.exists()) {
            try {
                in = assetManager.open("sample.pdf");
                out = getActivity().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());
            }
        }
        else {
            Log.d("test", "file already exists");
        }
    }

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

}
于 2016-10-08T18:22:49.553 回答
-1

此代码适用于每个 android 版本:

活动:

import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.AssetManager;
import android.net.Uri;
import android.os.Environment;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v4.content.FileProvider;
import android.util.Log;
import android.widget.Toast;

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

import unimedbh.UnimedBH.R;


public class MainActivity extends Activity {

    private static final int MY_PERMISSION_REQUEST_STORAGE = 1;

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

        if (ContextCompat.checkSelfPermission(MainActivity.this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {

           ActivityCompat.requestPermissions(MainActivity.this, new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, MY_PERMISSION_REQUEST_STORAGE); 

        } else {
            copyReadAssets("YOUR_PDF_NAME.pdf");
        }
    }


    private void copyReadAssets(String fileName) {
        String dirPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/MyFiles";
        File dir = new File(dirPath);

        if (!dir.exists()) {
            dir.mkdirs();
        }

        AssetManager assetManager = getAssets();
        InputStream in = null;
        OutputStream out = null;

        try {
            in = assetManager.open(fileName);
            File outFile = new File(dirPath, fileName);
            out = new FileOutputStream(outFile);
            copyFile(in, out);

            Intent intent = new Intent(Intent.ACTION_VIEW, FileProvider.getUriForFile(this, "com.package.name.fileprovider", outFile));
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_ACTIVITY_NO_HISTORY);

            startActivity(intent);
        } catch (IOException e) {
            e.printStackTrace();
            Toast.makeText(this, "Error!", Toast.LENGTH_SHORT).show();
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

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

清单.xml:

<provider
        android:name="android.support.v4.content.FileProvider"
        android:authorities="com.package.name.fileprovider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/file_paths" />
</provider>

文件路径.xml:

<paths>
    <files-path name="app_directory" path="directory/"/>
</paths>

在 API 16-28 中测试,适用于所有 API!

于 2018-06-11T19:39:07.187 回答