为什么内部存储中的 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;
我的服务器上有一个 .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;