为什么内部存储中的 pdf 没有显示在 webview 中

why is pdf from internal storage not showing in webview

我的服务器上有一个 .pdf 文件(可以每天更改内容,因此必须每天下载),使用 Volley 下载到设备。 api 使用身份验证令牌。

我可以使用 context.getExternalFilesDir 成功调用网络服务并将 pdf (byte[]) 写入我的应用程序的内部存储。

我遇到的问题是,一旦保存了 pdf 并构建了路径,webView 将不会显示 pdf。 webView 工作正常,因为我通过在项目的原始目录中放置一个测试 html 来完成测试。 webView可以正常显示。

以下不加载pdf。

webView.loadUrl("file://" + f2.getAbsolutePath());

我设备上的 f2 路径是

f2.getAbsolutePath() = /storage/emulated/0/Android/data/com.xxxx.rrx/files/careplans/careplan.pdf

似乎没有错误,但 pdf 没有加载。

我试过的:

我已经尝试更改 webView 的 webSettings 以允许文件访问。

WebSettings webViewSettings = webView.getSettings();
                // Setting this off for security. Off by default for SDK versions >= 16.
                webViewSettings.setAllowFileAccessFromFileURLs(true);
                // Off by default, deprecated for SDK versions >= 30.
                webViewSettings.setAllowUniversalAccessFromFileURLs(true);
                // Keeping these off is less critical but still a good idea, especially if your app is not
                // using file:// or content:// URLs.
                webViewSettings.setAllowFileAccess(true);
                webViewSettings.setAllowContentAccess(true);

有没有人知道为什么当 pdf 存储在应用程序自己的存储中时,webview 不显示它?

这是我的完整 class。

import android.app.DownloadManager;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.util.Base64;
import android.util.Log;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;

import com.android.volley.VolleyError;

import org.json.JSONObject;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;

public class DownloadCarePlanActivity extends AppCompatActivity {

    private static final String TAG = DownloadCarePlanActivity.class.getSimpleName();
    DownloadManager manager;
    long reference;
    String url;
    Context context;
    String fileName;
    WebView webView;


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

        Log.e(TAG, "inside onCreate" );

        context = getApplicationContext();

        webView = (WebView)findViewById(R.id.webViewCareplan);

        url = "https://xxx/api/xxx/careplan/1";




            WebServicesForWebApi webServices = new WebServicesForWebApi(DownloadCarePlanActivity.this, new WebServicesForWebApi.IResultForFile() {
                @Override
                public void notifySuccess(byte[]  response, String responseString) {

                    //responseString = responseString.replace('\', ' ');

                    Log.e(TAG, "formatted result for pdf webservice = " + response);

                    byte[] result;


                    if(response != null){

                        try {
                            byte[] bytes = response;
                            saveToFile(bytes, "careplan.pdf");
                        }catch (Exception e){
                            Toast.makeText(DownloadCarePlanActivity.this, "Error downloading pdf and saving it", Toast.LENGTH_LONG).show();
                        }

                    }





                }

                @Override
                public void notifyError(VolleyError error) {

                    Toast.makeText(DownloadCarePlanActivity.this, "There was a problem in sendFireBaseTokenToServerWAPI", Toast.LENGTH_LONG).show();

                }
            });







            JSONObject js = new JSONObject();
            /*try {


                js.put("carerId", "0");
                js.put("phoneId", fireBaseToken);


            } catch (JSONException e) {
                e.printStackTrace();
            }*/

            webServices.makeWebApiPostForFile(url, js);






    }//end of onCreate


    public void saveToFile(byte[] byteArray, String pFileName){
        //File f = new File(Environment.getExternalStorageDirectory() + "/careplans");

        File f = getAbsoluteFile("/careplans", context);
        Log.e(TAG, "f.path = " + f.getAbsolutePath());

        if(f.isDirectory()){
            f.delete();
        }

        if (!f.isDirectory()) {
            f.mkdir();
        }

        //String fileName = Environment.getExternalStorageDirectory() + "/careplans/" + pFileName;
         fileName = f.getAbsolutePath() + "/" + pFileName;
        Log.e(TAG, "String fileName = " + fileName);

        try {

            FileOutputStream fPdf = new FileOutputStream(fileName);

            fPdf.write(byteArray);
            fPdf.flush();
            fPdf.close();
            Toast.makeText(this, "File successfully saved", Toast.LENGTH_LONG).show();

            try {

                File f2 = new File(fileName);
                Log.e(TAG, "f2.getAbsolutePath() = " + f2.getAbsolutePath());
                Log.e(TAG, "f2.getCanonicalPath() = " + f2.getCanonicalPath());

                Log.e(TAG, "loading file in webview" );


                WebSettings webViewSettings = webView.getSettings();
                // Setting this off for security. Off by default for SDK versions >= 16.
                webViewSettings.setAllowFileAccessFromFileURLs(true);
                // Off by default, deprecated for SDK versions >= 30.
                webViewSettings.setAllowUniversalAccessFromFileURLs(true);
                // Keeping these off is less critical but still a good idea, especially if your app is not
                // using file:// or content:// URLs.
                webViewSettings.setAllowFileAccess(true);
                webViewSettings.setAllowContentAccess(true);


                webView.loadUrl("file://" + f2.getAbsolutePath());
                //webView.loadUrl("file:///android_res/raw/index.html");




                Log.e(TAG, "finished loading file in webview" );

            }catch(Exception e){

                final Writer result = new StringWriter();
                final PrintWriter printWriter = new PrintWriter(result);
                e.printStackTrace(printWriter);
                String stacktrace = result.toString();
                printWriter.close();

                Log.e(TAG, "stack = " + stacktrace);


            }

        } catch (FileNotFoundException e) {
            Toast.makeText(this, "File create error", Toast.LENGTH_LONG).show();
        } catch (IOException e) {
            Toast.makeText(this, "File write error", Toast.LENGTH_LONG).show();
        }




    }


    @Override
    protected void onResume() {
        super.onResume();



    }

    @Override
    protected void onPause() {
        super.onPause();



    }

    private File getAbsoluteFile(String relativePath, Context context) {
        if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
            return new File(context.getExternalFilesDir(null), relativePath);
        } else {
            return new File(context.getFilesDir(), relativePath);
        }
    }



}

好吧,WebView 是为打开网页而设计的,PDF 不是这种内容类型...是的,桌面浏览器可以做到这一点,甚至一些移动浏览器也可以,但这是附加功能。在 WebView 中不可用,您必须自己处理此类文件(例如使用 PdfRenderer). another way is to use some library, first example from search engine: AndroidPdfViewer on GitHub

编辑:刚刚意识到您的 PDF 只是本地的,所以下面可能不适合您...

更简单的方法是使用一些网络应用程序,它可以读取 PDF 并将其显示为网页,供 WebView 阅读。例如尝试在 URL

以下加载
String pdfUrl = "https://docs.google.com/gview?embedded=true&url=" + realPdfUrl;