如何使用 ContentProvider 从资产中的任何 pdf 应用程序打开 pdf

How to open pdf with any pdf app from assets using ContentProvider

首先,我知道这个问题被问过很多次,你可以确定我阅读并尝试了所有这些问题,但遗憾的是我没能成功。我需要再次询问 android 开发中的所有新手。顺便说一句,我正在向 udacity 学习。 我正在尝试从资产中打开 pdf 文件。我找到了这个 (cw-omnibus ContentProvider),这非常有用,但它不是动态的,我无法弄清楚如何为所有 pdf 制作动态的。基本上,每当我想通过按钮、cardview 等打开 pdf 时,它应该使用 fileprovider 打开。 简单地说,我可以用另一个名称复制和粘贴 FileProvider,然后我就可以使用它了。但是如果我有 20 个 pdf,我将有很多 java 文件。这就像步行而不是乘坐公共汽车去另一个城市。我只是想学习如何去做。我也不太了解java。我试了很多方法想坐公共汽车,但还是找不到公共汽车。我需要一些帮助。 在 github 示例中,有一个 "test.pdf" 是静态的,如您所见。当intent被调用时"test.pdf"开启。我厌倦了为 test.pdf 分配变量并尝试为 cardview(如按钮)切换大小写但我无法从 FileProvider.java 调用变量并且我厌倦了 bla bla bla 很多事情。 :(( 我知道我可以用 recyclerview 做 cardview,但我很难理解和定制,所以我手动创建了 cardview。 我在下面分享我的所有代码。

XML

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/colorBg"
    android:fillViewport="true"
    tools:context="com.example.tk.buzebv2.Hizmetlerimiz">

    <LinearLayout xmlns:card_view="http://schemas.android.com/apk/res-auto"
        android:id="@+id/activity_kilavuzlar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:paddingBottom="@dimen/activity_vertical_margin"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin">

        <android.support.v7.widget.CardView xmlns:card_view="http://schemas.android.com/apk/res-auto"
            android:id="@+id/card_clicked1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginBottom="@dimen/card_view_bottom"
            android:clickable="true"
            android:foreground="?android:attr/selectableItemBackground"
            android:onClick="onClick"
            card_view:cardCornerRadius="4dp">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical">

                <ImageView
                    android:id="@+id/imageView2"
                    android:layout_width="match_parent"
                    android:layout_height="150dp"
                    android:scaleType="centerCrop"
                    android:src="@drawable/hizmetlerimiz1" />

                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:paddingLeft="16dp"
                    android:paddingTop="16dp"
                    android:text="Uzaktan Öğretim Sınıfı"
                    android:textColor="@color/colorDefaultText"
                    android:textSize="24sp" />

                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:background="@android:color/white"
                    android:gravity="left"
                    android:lineSpacingMultiplier="1.3"
                    android:padding="@dimen/activity_horizontal_margin"
                    android:text="@string/hakkimizda_aciklama1"
                    android:textColor="@color/colorDefaultText"
                    android:textSize="16sp" />


            </LinearLayout>
        </android.support.v7.widget.CardView>

        <android.support.v7.widget.CardView xmlns:card_view="http://schemas.android.com/apk/res-auto"
            android:id="@+id/card_clicked2"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginBottom="@dimen/card_view_bottom"
            android:clickable="true"
            android:foreground="?android:attr/selectableItemBackground"
            android:onClick="onClick"
            card_view:cardCornerRadius="4dp">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical">

                <ImageView
                    android:layout_width="match_parent"
                    android:layout_height="150dp"
                    android:scaleType="centerCrop"
                    android:src="@drawable/hizmetlerimiz2" />

                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:paddingLeft="16dp"
                    android:paddingTop="16dp"
                    android:text="Uzaktan Öğretim Hizmetleri"
                    android:textColor="@color/colorDefaultText"
                    android:textSize="24sp" />

                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:background="@android:color/white"
                    android:gravity="left"
                    android:lineSpacingMultiplier="1.3"
                    android:padding="@dimen/activity_horizontal_margin"
                    android:text="@string/hakkimizda_aciklama3"
                    android:textColor="@color/colorDefaultText"
                    android:textSize="16sp" />


            </LinearLayout>
        </android.support.v7.widget.CardView>

        <android.support.v7.widget.CardView xmlns:card_view="http://schemas.android.com/apk/res-auto"
            android:id="@+id/card_clicked3"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginBottom="@dimen/card_view_bottom"
            android:clickable="true"
            android:foreground="?android:attr/selectableItemBackground"
            android:onClick="onClick"
            card_view:cardCornerRadius="4dp">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical">

                <ImageView
                    android:layout_width="match_parent"
                    android:layout_height="150dp"
                    android:scaleType="centerCrop"
                    android:src="@drawable/hizmetlerimiz3" />

                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:paddingLeft="16dp"
                    android:paddingTop="16dp"
                    android:text="Online Sınav Hizmetleri"
                    android:textColor="@color/colorDefaultText"
                    android:textSize="24sp" />

                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:background="@android:color/white"
                    android:gravity="left"
                    android:lineSpacingMultiplier="1.3"
                    android:padding="@dimen/activity_horizontal_margin"
                    android:text="@string/hakkimizda_aciklama3"
                    android:textColor="@color/colorDefaultText"
                    android:textSize="16sp" />


            </LinearLayout>
        </android.support.v7.widget.CardView>


    </LinearLayout>
</ScrollView>

JAVA

package com.example.tk.buzebv2;

import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.CardView;
import android.util.Log;
import android.view.View;


public class Hizmetlerimiz extends AppCompatActivity implements View.OnClickListener  {

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


        CardView b1= (CardView) findViewById(R.id.card_clicked1);
        CardView b2= (CardView) findViewById(R.id.card_clicked2);
        CardView b3= (CardView) findViewById(R.id.card_clicked3);
        b1.setOnClickListener(this);
        b2.setOnClickListener(this);
        b3.setOnClickListener(this);

    }


    public void onClick(View v) {

        int i = v.getId();
        if (i == R.id.card_toast) {
            String hizmet_01 = "hizmet_01_a201.pdf";
            startActivity(new Intent(Intent.ACTION_VIEW,
                    Uri.parse(FileProvider.CONTENT_URI
                            + hizmet_01)));

        } else if (i == R.id.card_toast1) {
            String hizmet_02 = "hizmet_02_distance.pdf";
            startActivity(new Intent(Intent.ACTION_VIEW,
                    Uri.parse(FileProvider.CONTENT_URI
                            + hizmet_02)));


        } else if (i == R.id.card_toast2) {
            String hizmet_03 = "hizmet_03_online_sinav.pdf";
            startActivity(new Intent(Intent.ACTION_VIEW,
                    Uri.parse(FileProvider.CONTENT_URI
                            + hizmet_03)));


        }

    }
}

FileProvider.java

/***
  Copyright (c) 2008-2014 CommonsWare, LLC
  Licensed under the Apache License, Version 2.0 (the "License"); you may not
  use this file except in compliance with the License. You may obtain a copy
  of the License at http://www.apache.org/licenses/LICENSE-2.0. Unless required
  by applicable law or agreed to in writing, software distributed under the
  License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
  OF ANY KIND, either express or implied. See the License for the specific
  language governing permissions and limitations under the License.

  From _The Busy Coder's Guide to Android Development_
    https://commonsware.com/Android
 */

package com.commonsware.android.cp.files;

import android.content.res.AssetManager;
import android.net.Uri;
import android.os.ParcelFileDescriptor;
import android.util.Log;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;

public class FileProvider extends AbstractFileProvider {
  public static final Uri CONTENT_URI=
      Uri.parse("content://com.commonsware.android.cp.files/");

  @Override
  public boolean onCreate() {
    File f=new File(getContext().getFilesDir(), "test.pdf");

    if (!f.exists()) {
      AssetManager assets=getContext().getResources().getAssets();

      try {
        copy(assets.open("test.pdf"), f);
      }
      catch (IOException e) {
        Log.e("FileProvider", "Exception copying from assets", e);

        return(false);
      }
    }

    return(true);
  }

  @Override
  public ParcelFileDescriptor openFile(Uri uri, String mode)
    throws FileNotFoundException {
    File root=getContext().getFilesDir();
    File f=new File(root, uri.getPath()).getAbsoluteFile();

    if (!f.getPath().startsWith(root.getPath())) {
      throw new
        SecurityException("Resolved path jumped beyond root");
    }

    if (f.exists()) {
      return(ParcelFileDescriptor.open(f, parseMode(mode)));
    }

    throw new FileNotFoundException(uri.getPath());
  }

  @Override
  protected long getDataLength(Uri uri) {
    File f=new File(getContext().getFilesDir(), uri.getPath());

    return(f.length());
  }

  // following is from ParcelFileDescriptor source code
  // Copyright (C) 2006 The Android Open Source Project
  // (even though this method was added much after 2006...)

  private static int parseMode(String mode) {
    final int modeBits;
    if ("r".equals(mode)) {
      modeBits=ParcelFileDescriptor.MODE_READ_ONLY;
    }
    else if ("w".equals(mode) || "wt".equals(mode)) {
      modeBits=
          ParcelFileDescriptor.MODE_WRITE_ONLY
              | ParcelFileDescriptor.MODE_CREATE
              | ParcelFileDescriptor.MODE_TRUNCATE;
    }
    else if ("wa".equals(mode)) {
      modeBits=
          ParcelFileDescriptor.MODE_WRITE_ONLY
              | ParcelFileDescriptor.MODE_CREATE
              | ParcelFileDescriptor.MODE_APPEND;
    }
    else if ("rw".equals(mode)) {
      modeBits=
          ParcelFileDescriptor.MODE_READ_WRITE
              | ParcelFileDescriptor.MODE_CREATE;
    }
    else if ("rwt".equals(mode)) {
      modeBits=
          ParcelFileDescriptor.MODE_READ_WRITE
              | ParcelFileDescriptor.MODE_CREATE
              | ParcelFileDescriptor.MODE_TRUNCATE;
    }
    else {
      throw new IllegalArgumentException("Bad mode '" + mode + "'");
    }
    return modeBits;
  }
}

最简单的方法是使用 my StreamProvider,它会为您处理所有这些 "out of the box"。它基于 Android 支持库提供的 FileProvider,但它直接从资产中提供文件服务,而无需您查看的我的特定示例应用程序制作的干预副本。

否则,您那里的示例将处理任意数量的 PDF。恰好在onCreate()中只设置了一个。您可以改为让 onCreate() 派生一个后台线程并设置任意数量的 PDF。 ContentProvider 中的其余代码不需要更改,因为它只是根据 Uri.

中提供的文件名查找 getFilesDir() 中的文件