why is pdf from internal storage not showing in webview
I have a .pdf file (which can change content daily, so must be downloaded daily) on my server which is downloaded to the device using Volley. The api uses authentication tokens.
I can successfully call the web service and write the pdf (byte[]) to my app's internal storage by using context.getExternalFilesDir.
The problem i am having is once the pdf is saved and i contruct the path, the webView will not show the pdf. The webView is working fine as i have done a test by placing a test html in the project's raw directory. The webView can display this fine.
The following does not load the pdf.
webView.loadUrl("file://" + f2.getAbsolutePath());
f2 path on my device is
f2.getAbsolutePath() = /storage/emulated/0/Android/data/com.xxxx.rrx/files/careplans/careplan.pdf
There seems to be no error but the pdf does not load.
What i have tried:
i've tried changing the webSettings for the webView to allow file access.
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);
Does anyone have any ideas why the webview does not show the pdf when it is stored in the app's own storage?
here is my complete 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);
}
}
}
well, WebView
is designed to open web pages, PDF isn't such content type... yeah, desktop browser can do it, even some mobile ones, but this is additional feature. not available in WebView
, you have to handle such file by yourself (e.g. using PdfRenderer
). another way is to use some library, first example from search engine: AndroidPdfViewer on GitHub
edit: just realised that your PDF is local only, so below probably isn't an option for you...
way simpler would be to use some web application, which can read PDF and show it as a web page, readable by WebView
. for example try to load below URL
String pdfUrl = "https://docs.google.com/gview?embedded=true&url=" + realPdfUrl;