Android: Viewing pdf in Webview using GoogleDocs - android

I am trying to open pdf links in my webview using Google Docs. The Webview initially accepts the url but in log cat i notice that at some point the url changes to "about:blank" and in the end it load only a blank page.
I have also overriden onPageStarted and onPageFinished methods and noticed that when shouldOvverideUrlLoading is called the second time by the WebView it changes the url to "about:blank"
Any thoughts on why this happens?
#Override
public boolean shouldOverrideUrlLoading(String url) {
getView().loadWebview(url);
}
#Override
public void loadWebview(String url) {
String pdfSuffix = ".pdf";
String googleDocsUrl = "http://docs.google.com/viewer?url=" + url;
if (url.endsWith(pdfSuffix)) {
Logger.i(LOG_TAG, "pdf loadwebview: url= " + googleDocsUrl);
mView.loadUrl(googleDocsUrl);
} else {
Logger.i(LOG_TAG, "loadwebview: url= " + url);
mView.loadUrl(url);
}
}

Related

Inject JS/CSS before WebView show up

I've seen several questions on this but all of the solutions didn't work for me. For a client we have to develop an app that actually does nothing except of showing a WebView and a native DrawerLayout. However, we only have their mobile webpage (with a menu, etc.). So we have to hide some elements. It is very important that the existing stylesheets stay the same, just some other CSS rules are added.
What I've tried so far:
#Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
if (!mErrorOccured && !noConnectionAvailable) {
injectCSS();
}
mainActivity.hideLoadingScreen();
}
With this Injection:
// Inject CSS method: read style.css/readmode.css from assets folder
// Append stylesheet to document head
private void injectCSS() {
try {
Activity activity = (Activity) mContext;
SharedPreferences sharPref = activity.getSharedPreferences(Constants.PREFERENCE_NAME, Context.MODE_PRIVATE);
Boolean isReadMode = sharPref.getBoolean(Constants.READMODE_KEY, false);
InputStream inputStream;
if (isReadMode) {
inputStream = activity.getAssets().open("readmode.css");
} else {
inputStream = activity.getAssets().open("style.css");
}
byte[] buffer = new byte[inputStream.available()];
inputStream.read(buffer);
inputStream.close();
String encoded = Base64.encodeToString(buffer, Base64.NO_WRAP);
webView.loadUrl("javascript:(function() {" +
"var parent = document.getElementsByTagName('head').item(0);" +
"var style = document.createElement('style');" +
"style.type = 'text/css';" +
// Tell the browser to BASE64-decode the string into your script !!!
"style.innerHTML = window.atob('" + encoded + "');" +
"parent.appendChild(style);" +
"Android.injectCSS('Works!');})()");
} catch (Exception e) {
e.printStackTrace();
}
}
I've also tried to add a JavaScript Interface that uses the Android.injectCSS('Works!'); of the JavaScript above combined with:
#JavascriptInterface
public void injectCSS(String toast) {
Toast.makeText(mContext, toast, Toast.LENGTH_LONG).show();
mMainActivity.runOnUiThread(new Runnable() {
#Override
public void run() {
mMainFragment.unhideWebView();
}
});
}
And:
public void unhideWebView() {
webView.setVisibility(View.VISIBLE);
}
However, there is always a delay before the elements of the web page are hidden. I've also tried to use Jsoup. First this threw an NetworkOnMainThreadException. After I've tried to use it with an AsyncTask, it was not possible to change the WebView on onPostExecute() because this handling must be on the main thread. Even using a runOnUiThrad() did not help calling loadData() on the WebView with the new loaded data.
Is there any way to inject CSS/JS before the WebView shows up?

Access Meta Data from android WebView

How to access Meta Data of a HTML page loaded into a WebView in Android?
I search for hours stackoverflow.com and google and I coudn't find any answer.
I only could get url and title by this code:
webView.getTitle();
webView.getUrl();
Dose is it imposible and webview not support it?
Don't open the URL in the WebView.
First. open an HttpURLConnection to the URL. Read the output from the server and you can scan through the server response to find your meta data.
As you are reading the server output, write the data into a buffer, then use loadData instead of loadUrl to display the buffered data in the WebView
You can solve the problem by this easy way:
private class JsInterface {
#JavascriptInterface
#SuppressWarnings("unused")
public void processHTML(String content) {
//handle content
}
}
mWebView.addJavascriptInterface(new JsInterface(), "CC_FUND");
mWebView.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url) {
mWebView.loadUrl("javascript:window.CC_FUND.processHTML( (function (){var metas = document.getElementsByTagName('meta'); \n" +
"\n" +
" for (var i=0; i<metas.length; i++) { \n" +
" if (metas[i].getAttribute(\"name\") == \"description\") { \n" +
" return metas[i].getAttribute(\"content\"); \n" +
" } \n" +
" } \n" +
"\n" +
" return \"\";})() );");
super.onPageFinished(view, url);
}
}
If its your own web page then you can pass the meta description or any text to your app using the below code:
public class WebAppInterface {
#JavascriptInterface
public void setDesc(String desc) {
mDescription = desc;
}
}
Then add JS interface to WebView:
webView.addJavascriptInterface(new WebAppInterface(), "Android");
Finally, add the following code in your webpage:
<script type="text/javascript">
Android.setDesc("Your meta tag desc here");
</script>
Read more at https://developer.android.com/guide/webapps/webview.html

Android PDF not loading in browser and WebView

I am trying to load PDF files in Android Webview. when i Googled it. the best answer what i found is to use Google Docs. Now What i did is append the PDF file URL at the end of this url
https://docs.google.com/gview?embedded=true&url=
and then load this complete URL in the android WebView. it loads the PDF successfully. But there is one PDF file on the following URL that is not loading in WebView as well as in Chrome browser (on my system). The PDF URL is
http://www.expertagent.co.uk/asp/in4glestates/{16D968D6-198E-4E33-88F4-8A85731CE605}/{05c36123-4df0-4d7d-811c-8b6686fdd526}/external.pdf
and When i try to load the PDF as
https://docs.google.com/gview?embedded=true&url=www.expertagent.co.uk/asp/in4glestates/{16D968D6-198E-4E33-88F4-8A85731CE605}/{05c36123-4df0-4d7d-811c-8b6686fdd526}/external.pdf
then it says No Preview Available. can anyone please tell me whats wrong Here.
This is not a complete answer. I investigated several possibilities but still do not have a convincing explanation for this behavior.
Theory A: URL encoding ... no
My first thought was the same as #gn1 - the curly brackets needed URL encoding. Unfortunately, encoding the url parameter doesn't change the result.
Theory B: Bad PDF file ... no
Next I thought that perhaps Google Docs can't handle this particular PDF file - it's an unsupported version or uses optional features or even has errors that other viewers tolerate. I downloaded a copy and hosted it on another site. When I pointed Google Docs to the new location, it previewed fine.
Theory C: Uncooperative site ... no
Next I thought that maybe this site doesn't cooperate with Google Docs for some reason - perhaps it is blocking Google from indexing it. I found another PDF link on the same site with the same scheme:
http://www.expertagent.co.uk/asp/in4glestates/%7B6dad6f28-a59d-4b54-b277-52f077f4927f%7D/%7Be3a6d17c-d6a8-4e92-8f52-09c6721515fc%7D/External.pdf
When I pointed Google Docs to this link, it previewed fine.
Theory D: Different metadata ... no
Now I had one link that worked and one that didn't. Maybe their metadata was different - e.g. perhaps the one that worked was tagged application/pdf and the other one wasn't. So I looked at the HTTP headers.
Working URL:
HTTP/1.1 200 OK
Cache-Control: max-age=3600
Content-Length: 1767120
Content-Type: application/pdf
Last-Modified: Fri, 02 Nov 2007 12:45:00 GMT
Accept-Ranges: bytes
ETag: "46b1592e4e1dc81:13e6"
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET
Date: Wed, 03 Jun 2015 23:25:23 GMT
Not working URL:
HTTP/1.1 200 OK
Cache-Control: max-age=3600
Content-Length: 4623702
Content-Type: application/pdf
Last-Modified: Mon, 11 May 2015 15:53:16 GMT
Accept-Ranges: bytes
ETag: "acac5d9828cd01:13e6"
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET
Date: Wed, 03 Jun 2015 23:25:42 GMT
I see no apparent significant differences in metadata.
Theory E: Weird request from Google ... no
I'm admittedly grasping at straws at this point. I wondered if the request from Google was different somehow - maybe it asked for a byte range or obscure compression or something, and the target server didn't handle it consistently well. So I pointed Google Docs at a site I control to see what the HTTP request looked like:
GET /asp/in4glestates/%7B16D968D6-198E-4E33-88F4-8A85731CE605%7D/%7B05c36123-4df0-4d7d-811c-8b6686fdd526%7D/External.pdf HTTP/1.1
Host: www.example.com:55555
Connection: Keep-alive
Accept-Encoding: gzip,deflate
User-Agent: Mozilla/5.0 (compatible; Google AppsViewer; http://drive.google.com)
That isn't weird at all. I did verify that the target site ignores compression requests so it isn't a case of buggy compression. I also tried accessing the target site with that User-Agent header and it didn't seem to matter.
So I've found clues that help tell us what isn't the problem but nothing yet that explains what is. I'm posting in hopes that these negative results will still be useful to someone.
I'm using this and works for me: http://weimenglee.blogspot.com/2013/05/android-tip-displaying-pdf-document.html
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
WebView webView=new WebView(MainActivity.this);
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setPluginState(WebSettings.PluginState.ON);
//---you need this to prevent the webview from
// launching another browser when a url
// redirection occurs---
webView.setWebViewClient(new Callback());
String pdfURL = "http://www.expertagent.co.uk/asp/in4glestates/{16D968D6-198E-4E33-88F4-8A85731CE605}/{05c36123-4df0-4d7d-811c-8b6686fdd526}/external.pdf";
webView.loadUrl(
"http://docs.google.com/gview?embedded=true&url=" + pdfURL);
setContentView(webView);
}
private class Callback extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(
WebView view, String url) {
return(false);
}
}
Checkout the example code for open PDF without download, in webview
.
private void init()
{
WebView webview = (WebView) findViewById(R.id.webview);
WebSettings settings = webview.getSettings();
settings.setJavaScriptEnabled(true);
webview.setScrollBarStyle(WebView.SCROLLBARS_OUTSIDE_OVERLAY);
PdfWebViewClient pdfWebViewClient = new PdfWebViewClient(this, webview);
pdfWebViewClient.loadPdfUrl(
"https://www.google.co.in/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&ved=0ahUKEwjgwIfp3KXSAhXrhFQKHQqEDHYQFggZMAA&url=http%3A%2F%2Fwww.orimi.com%2Fpdf-test.pdf&usg=AFQjCNERYYcSfMLS5ukBcT2Qy11YxEhXqw&cad=rja");
}
private class PdfWebViewClient extends WebViewClient
{
private static final String TAG = "PdfWebViewClient";
private static final String PDF_EXTENSION = ".pdf";
private static final String PDF_VIEWER_URL = "http://docs.google.com/gview?embedded=true&url=";
private Context mContext;
private WebView mWebView;
private ProgressDialog mProgressDialog;
private boolean isLoadingPdfUrl;
public PdfWebViewClient(Context context, WebView webView)
{
mContext = context;
mWebView = webView;
mWebView.setWebViewClient(this);
}
public void loadPdfUrl(String url)
{
mWebView.stopLoading();
if (!TextUtils.isEmpty(url))
{
isLoadingPdfUrl = isPdfUrl(url);
if (isLoadingPdfUrl)
{
mWebView.clearHistory();
}
showProgressDialog();
}
mWebView.loadUrl(url);
}
#SuppressWarnings("deprecation")
#Override
public boolean shouldOverrideUrlLoading(WebView webView, String url)
{
return shouldOverrideUrlLoading(url);
}
#SuppressWarnings("deprecation")
#Override
public void onReceivedError(WebView webView, int errorCode, String description, String failingUrl)
{
handleError(errorCode, description.toString(), failingUrl);
}
#TargetApi(Build.VERSION_CODES.N)
#Override
public boolean shouldOverrideUrlLoading(WebView webView, WebResourceRequest request)
{
final Uri uri = request.getUrl();
return shouldOverrideUrlLoading(webView, uri.toString());
}
#TargetApi(Build.VERSION_CODES.N)
#Override
public void onReceivedError(final WebView webView, final WebResourceRequest request, final WebResourceError error)
{
final Uri uri = request.getUrl();
handleError(error.getErrorCode(), error.getDescription().toString(), uri.toString());
}
#Override
public void onPageFinished(final WebView view, final String url)
{
Log.i(TAG, "Finished loading. URL : " + url);
dismissProgressDialog();
}
private boolean shouldOverrideUrlLoading(final String url)
{
Log.i(TAG, "shouldOverrideUrlLoading() URL : " + url);
if (!isLoadingPdfUrl && isPdfUrl(url))
{
mWebView.stopLoading();
final String pdfUrl = PDF_VIEWER_URL + url;
new Handler().postDelayed(new Runnable()
{
#Override
public void run()
{
loadPdfUrl(pdfUrl);
}
}, 300);
return true;
}
return false; // Load url in the webView itself
}
private void handleError(final int errorCode, final String description, final String failingUrl)
{
Log.e(TAG, "Error : " + errorCode + ", " + description + " URL : " + failingUrl);
}
private void showProgressDialog()
{
dismissProgressDialog();
mProgressDialog = ProgressDialog.show(mContext, "", "Loading...");
}
private void dismissProgressDialog()
{
if (mProgressDialog != null && mProgressDialog.isShowing())
{
mProgressDialog.dismiss();
mProgressDialog = null;
}
}
private boolean isPdfUrl(String url)
{
if (!TextUtils.isEmpty(url))
{
url = url.trim();
int lastIndex = url.toLowerCase().lastIndexOf(PDF_EXTENSION);
if (lastIndex != -1)
{
return url.substring(lastIndex).equalsIgnoreCase(PDF_EXTENSION);
}
}
return false;
}
}
Here is working solution for 'No Preview Available' issue.. Exact Problem is in URL encoding which we concat with "http://docs.google.com/gview?url=". This means we have to replace all special character(:, /, & etc) of url with unicode. Uri.encode("") do the trick for us.
String url = Uri.encode("your link");
String finalUrl = "http://docs.google.com/viewer?url=" + url + "&embedded=true";
WebSettings webSettings = webView.getSettings();
webSettings.setBuiltInZoomControls(true);
webSettings.setJavaScriptEnabled(true);
webView.setScrollBarStyle(View.SCROLLBARS_OUTSIDE_OVERLAY);
webView.getSettings().setBuiltInZoomControls(true);
webView.getSettings().setUseWideViewPort(true);
webView.getSettings().setLoadWithOverviewMode(true);
progressView.setVisibility(View.VISIBLE);
webView.loadUrl(finalUrl);
webView.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url) {
view.getSettings().setLoadsImagesAutomatically(true);
webView.setVisibility(View.VISIBLE);
//progressView.setVisibility(View.VISIBLE);
if (progressView != null && progressView.isShown()) {
progressView.setVisibility(View.GONE);
}
Log.v("after load", view.getUrl());
}
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
}
#Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
Toast.makeText(getApplicationContext(), description, Toast.LENGTH_SHORT).show();
Log.e("error", description);
}
});
I put the file on my server and it works fine. This is a Google Docs problem encountered in the URL or the robots.txt. The document is fine. You can use URL rewrite to make Google Docs be fooled into thinking that it is from another folder. Those weird characters in the path could be the problem.
Clearly either a timing or browser issue the OP URL works perfectly via google as per given link (no need to convert or use any fancy coding) just retry with any other browser.
By the looks of things the URL you're pointing to includes some device specific location references.
You could look at downloading the file to internal store and then using an intent to load the PDF with any app installed.
From How to open a PDF via Intent from SD card
File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"/example.pdf");
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file), "application/pdf");
intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
startActivity(intent);
Alternatively you could instantiate the file with the web url
Download the source code from here(Open pdf in webview android);
activity_main.xml
<RelativeLayout android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
<WebView
android:layout_width="match_parent"
android:background="#ffffff"
android:layout_height="match_parent"
android:id="#+id/webview"></WebView>
</RelativeLayout>
MainActivity.java
package com.pdfwebview;
import android.app.ProgressDialog;
import android.graphics.Bitmap;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.webkit.WebView;
import android.webkit.WebViewClient;
public class MainActivity extends AppCompatActivity {
WebView webview;
ProgressDialog pDialog;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
listener();
}
private void init() {
webview = (WebView) findViewById(R.id.webview);
webview.getSettings().setJavaScriptEnabled(true);
pDialog = new ProgressDialog(MainActivity.this);
pDialog.setTitle("PDF");
pDialog.setMessage("Loading...");
pDialog.setIndeterminate(false);
pDialog.setCancelable(false);
webview.loadUrl("https://drive.google.com/file/d/0B534aayZ5j7Yc3RhcnRlcl9maWxl/view");
}
private void listener() {
webview.setWebViewClient(new WebViewClient() {
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
pDialog.show();
}
#Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
pDialog.dismiss();
}
});
}
}
Set the URL in the webview to this.
https://docs.google.com/viewer?url=<pdf-url>

WebView not posting/loading correctly

I have this piece of WebView code which should login to a website and then load a certain page of that website.
webView = (WebView) findViewById(R.id.recording_web_view);
Bundle b = getIntent().getExtras();
String filename = b.getString("filename");
SettingsManager setman = SettingsManager.getInstance(getBaseContext());
//Login to webinterface before we can watch the recording
String postData = "username=" + setman.getUserName() + "&password=" + setman.getPassword();
//This is the section of code that fixes redirects to external apps
webView.setWebViewClient(new WebViewClient(){
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url){
return false;
}
});
//Post login to get session
webView.postUrl("http://" + setman.getIp() + "/login", EncodingUtils.getBytes(postData, "BASE64"));
//Load actual recording
webView.loadUrl("http://" + setman.getIp() + "/movies/" + filename);
And when I run this I just get the login page, and the server says it received no postdata. However, when I remove the loadUrl line it does receive the login data and load the page after the login.
Can anyone tell me what I am doing wrong? Thanks
Try use in WebViewClient:
#Override
public void onPageFinished( WebView view, String url)
{
view.loadUrl( "http://" + setman.getIp() + "/movies/" + filename);
}
Also you can check error of request:
#Override
public void onReceivedError( WebView view, int errorCode, String description, String failingUrl)
Enable the the JavaScript
webView.getSettings().setJavaScriptEnabled(
true);

How to split up Epub Html into pages according to screen size

I'm developing an Android application that reads ebooks (in epub format) and as for now I'm using Paul Siegeman's epublib library that is really a very good epub reader but it has some limitations, for example and the one I need, you can't move through pages horizontally (as you do reading a real book) so I need my own implementation of it, but I'm stuck.
The method that actually reads the epub and then puts it inside a webview is the next:
private void openEpub(String bookFilename){
WebView webView = (WebView) findViewById(R.id.webView);
nl.siegmann.epublib.domain.Book book=null;
try {
book = (new EpubReader()).readEpub(new FileInputStream(Environment.getExternalStorageDirectory().getPath() + "/" + bookFilename));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
String baseUrl = Environment.getExternalStorageDirectory().getPath() + "/";
String data=null;
try {
data = new String(book.getContents().get(1).getData());
} catch (IOException e) {
e.printStackTrace();
}
webView.loadDataWithBaseURL(baseUrl, data, "text/html", "UTF-8", null);
}
So as you see I display the ebook in a webview so as far as I know the only scrolling possibility webview gives is up/down.
I was thinking on splitting the html string that getData() returns and webview loads into pages and displaying them one by one with a viewpager, but how to split the html correctly according to screen size?
Do you think with this idea I'm on the right way? Any other solutions to display epub from left to right / right to left (paginate) or any other "free or cheap" library to do so? (I tried PageTurner, it's really good, but the commercial version is too expensive for me)
I have done pagination effect in android like this..
-> create a custom webview class.
-> set below clients and load url then you will get horizontal scrolling with page count.
-> Lock the webview default scroll.
-> For smooth pagination effect instead of moving scroll of webview ,move the entire webview so for one page there would be one webview.
-> Use your own viewflippers to buffer previous and next pages.
I have done all these implementations and I made a product for an organisation.Just I am sharing my idea how to approach towards the best solution.Instead of using third parities and stucking in the middle due to limitation of that sdk ,make every thing your own.
private class MyWebClient extends WebViewClient
{
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
}
#Override
public void onPageFinished(WebView view, String url)
{
super.onPageFinished(view, url);
final MyWebView myWebView = (MyWebView) view;
String varMySheet = "var mySheet = document.styleSheets[0];";
String addCSSRule = "function addCSSRule(selector, newRule) {"
+ "ruleIndex = mySheet.cssRules.length;"
+ "mySheet.insertRule(selector + '{' + newRule + ';}', ruleIndex);"
+ "}";
String insertRule1 = "addCSSRule('html', 'padding: 0px; height: "
+ (myWebView.getMeasuredHeight()/getContext().getResources().getDisplayMetrics().density )
+ "px; -webkit-column-gap: 0px; -webkit-column-width: "
+ myWebView.getMeasuredWidth() + "px;')";
myWebView.loadUrl("javascript:" + varMySheet);
myWebView.loadUrl("javascript:" + addCSSRule);
myWebView.loadUrl("javascript:" + insertRule1);
}
}
private class MyWebChromeClient extends WebChromeClient
{
#Override
public void onProgressChanged(WebView view, int newProgress)
{
super.onProgressChanged(view, newProgress);
if(newProgress == 100)
{
postDelayed(new Runnable()
{
#Override
public void run()
{
calculateNoOfPages();
}
},200);
}
}
}
private void calculateNoOfPages()
{
if(GlobalSettings.EPUB_LAYOUT_TYPE == GlobalConstants.FIXED)
{
}
else
{
if(getMeasuredWidth() != 0)
{
int newPageCount = computeHorizontalScrollRange()/getMeasuredWidth();
getData().getChapterVO().setPageCount(newPageCount);
}
}
}
#Override
public int computeHorizontalScrollRange() {
// TODO Auto-generated method stub
return super.computeHorizontalScrollRange();
}
one you load url to
Follow this github account.
FbReader provide some great libraries for epub and pdf reader. Try this....
or
You can Make your own custom WebView by extending WebView. Here you can place and modify all the functionalities you want from your WebView.
My colleague made a reader using this FbReader and It was fabulous.
Hey I think this will help you. The answer by Nacho L worked for me. Here HTML book-like pagination?

Categories

Resources