Inject javascript file to my site with webview in android - javascript

I want to inject javascript file to my site. My site is a simple html page that is on server. I have injected css file. (with Manish's help)
So I can manage my simple html site with CSS now. But I want to manage it with javascript too. My jscript.js file is in asset folder. I want to have full access of javascript on my site. (Remember that, it is MY site) . please write the correct codes for me. Thankx.
Here is my MainActivity.java file:
package com.example.z5070.myapplication;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.util.Base64;
import android.view.Menu;
import android.view.MenuItem;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import java.io.InputStream;
public class MainActivity extends ActionBarActivity {
WebView webView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
webView = new WebView(this);
setContentView(webView);
webView.getSettings().setJavaScriptEnabled(true);
webView.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url) {
injectCSS();
super.onPageFinished(view, url);
}
});
webView.loadUrl("http://www.example.com/");
}
private void injectCSS() {
try {
InputStream inputStream = 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';" +
"style.innerHTML = window.atob('" + encoded + "');" +
"parent.appendChild(style)" +
"})()");
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}

Add a new method to inject javascript file.
private void injectJS() {
try {
InputStream inputStream = getAssets().open("jscript.js");
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 script = document.createElement('script');" +
"script.type = 'text/javascript';" +
"script.innerHTML = window.atob('" + encoded + "');" +
"parent.appendChild(script)" +
"})()");
} catch (Exception e) {
e.printStackTrace();
}
}
Call both methods: injectCSS() and injectJS() after page finishes loading.
webView.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url) {
injectCSS();
injectJS();
super.onPageFinished(view, url);
}
});
I hope this solves the problem.
Be wary of how onload events defined inside inject js file would behave.

Some refinements to previous answer. Suppose we use Cyrillic words. Result would be a garbaged strings. It's not good. With code below you can use non-english chars in content. Just add additional url-encoding/decoding to your code and you good to go. Reedited version below.
private void injectJS() {
try {
InputStream inputStream = getAssets().open("jscript.js");
byte[] buffer = new byte[inputStream.available()];
inputStream.read(buffer);
inputStream.close();
// preserve non-english letters
String uriEncoded = URLEncoder.encode(new String(buffer, "UTF-8"), "UTF-8").replace("+", "%20");
String encoded = Base64.encodeToString(uriEncoded.getBytes(), Base64.NO_WRAP);
webView.loadUrl("javascript:(function() {" +
"var parent = document.getElementsByTagName('head').item(0);" +
"var script = document.createElement('script');" +
"script.type = 'text/javascript';" +
// don't forget to use decodeURIComponent after base64 decoding
"script.innerHTML = decodeURIComponent(window.atob('" + encoded + "'));" +
"parent.appendChild(script)" +
"})()");
} catch (Exception e) {
e.printStackTrace();
}
}

Related

Dragging Image in CKEditor PrimeFaces

I am trying to upload image in CKEditor with image2 plugin.It is wokring fine when I am uploading it by 'send it to server' button but drag and drop of images is not working.
Below is Version Detail:
- Primefaces 6.0
- Ckeditor 4.9.1
- JSF 2.2
Config.js
CKEDITOR.editorConfig = function(config){
// config.timestamp='ABCD';
config.disableNativeSpellChecker = false;
config.pasteFromWordRemoveFontStyles=false;
config.pasteFromWordRemoveStyles=false;
config.allowedContent=true;
config.filebrowserBrowseUrl='#{request.contextPath}/CKEditorGetImageServlet';
config.filebrowserUploadUrl = 'CKEditorUploadServlet';
//config.filebrowserUploadMethod = "form";
config.uploadUrl='CKEditorUploadServlet';
config.extraPlugins = 'image2';
};
Upload Servlet:
public class CKEditorUploadServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private static final String ERROR_FILE_UPLOAD = "An error occurred to the file upload process.";
private static final String ERROR_NO_FILE_UPLOAD = "No file is present for upload process.";
private static final String ERROR_INVALID_CALLBACK = "Invalid callback.";
private static final String CKEDITOR_CONTENT_TYPE = "text/html; charset=UTF-8";
private static final String CKEDITOR_HEADER_NAME = "Cache-Control";
private static final String CKEDITOR_HEADER_VALUE = "no-cache";
private static final Pattern PATTERN = Pattern.compile("[\\w\\d]*");
private String errorMessage = "";
public CKEditorUploadServlet() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType(CKEDITOR_CONTENT_TYPE);
response.setHeader(CKEDITOR_HEADER_NAME, CKEDITOR_HEADER_VALUE);
final FileItemFactory factory = new DiskFileItemFactory();
final ServletFileUpload upload = new ServletFileUpload(factory);
List fileItems = null;
Iterator itr = null;
FileItem fi = null;
File file = null;
String contentType = "";
byte[] content;
String id = UUID.randomUUID().toString().substring(0, 8);
System.out.println(id);
final PrintWriter out = response.getWriter();
UploadBean bean = (UploadBean) getServletContext().getAttribute("uploadBean");
if (bean == null) {
bean = new UploadBean();
getServletContext().setAttribute("uploadBean", bean);
}
try {
/*final List items = upload.parseRequest(request);
if (!items.isEmpty() && items.get(0) != null) {
System.out.println("Content "+((DiskFileItem) items.get(0)).get());
System.out.println("Content Type "+((DiskFileItem) items.get(0)).getContentType());
System.out.println("Name "+((DiskFileItem) items.get(0)).getName());
} else {
//No file to Upload
}*/
fileItems = upload.parseRequest(request);
itr = fileItems.iterator();
while ( itr.hasNext () )
{
fi = (FileItem)itr.next();
if ( !fi.isFormField () )
{
String fileName = fi.getName();
System.out.println("FileName "+fileName);
String ext = fileName.substring(fileName.lastIndexOf(".")+1,fileName.length());
boolean isInMemory = fi.isInMemory();
contentType = fi.getContentType();
content = fi.get();
bean.setContent(fi.get());
long sizeInBytes = fi.getSize();
if( fileName.lastIndexOf("\\") >= 0 )
{
file = new File("D:\\Document" + "\\" + id + "." + ext) ;
}
else
{
file = new File("D:\\Document\\" + "\\" + id + "." + ext) ;
}
fi.write( file ) ;
}
}
bean.setId(id);
bean.setContentType(contentType);
} catch (Exception e) {
e.printStackTrace();
}
finally
{
fileItems = null;
itr = null;
fi = null;
}
// CKEditorFuncNum Is the location to display when the callback
// String callback = request.getParameter("CKEditorFuncNum");
String callback ="1";
System.out.println("Callback "+callback);
// verify if the callback contains only digits and letters in order to
// avoid vulnerability on parsing parameter
if (!PATTERN.matcher(callback).matches()) {
System.out.println("Patten not matches");
callback = "";
errorMessage = ERROR_INVALID_CALLBACK;
}
final String pathToFile = request.getContextPath()
+ "/CKEditorGetImageServlet?imageId=" + bean.getId();
System.out.println("Path to File "+pathToFile);
out.println("<script type='text/javascript'>window.parent.CKEDITOR.tools.callFunction("
+ callback + ",'" + pathToFile + "','" + errorMessage + "')");
out.println("// ]]></script>");
out.flush();
out.close();
}
}
GetImage Servlet
public class CKEditorGetImageServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private static final String ERROR_FILE_DOWNLOAD = "An error occured when trying to get the image with id:";
private static final String IMAGE_PARAMETER_NAME = "imageId";
private static final long CACHE_AGE_MILISECONDS_TWO_WEEKS = 1209600000;
private static final String CKEDITOR_CONTENT_EXPIRE = "Expires";
private static final String CKEDITOR_CONTENT_TYPE = "Content-Type";
private static final String CKEDITOR_CONTENT_LENGTH = "Content-Length";
private static final String CKEDITOR_CONTENT_DISPOSITION = "Content-Disposition";
private static final String CKEDITOR_CONTENT_DISPOSITION_VALUE = "inline; filename=\"";
private static final String CKEDITOR_HEADER_NAME = "Cache-Control";
public CKEditorGetImageServlet() {
super();
// TODO Auto-generated constructor stub
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
UploadBean bean = (UploadBean) getServletContext().getAttribute("uploadBean");
final byte[] rb = bean.getContent();
System.out.println("Inside get Image Servlet "+rb);
System.out.println("Content Type "+bean.getContentType());
final long expiry = new Date().getTime()
+ CACHE_AGE_MILISECONDS_TWO_WEEKS;
response.setDateHeader(CKEDITOR_CONTENT_EXPIRE, expiry);
response.setHeader(CKEDITOR_HEADER_NAME, "max-age="
+ CACHE_AGE_MILISECONDS_TWO_WEEKS);
response.setHeader(CKEDITOR_CONTENT_TYPE,
bean.getContentType());
response.setHeader(CKEDITOR_CONTENT_LENGTH,
String.valueOf(rb.length));
response.setHeader(
CKEDITOR_CONTENT_DISPOSITION,
CKEDITOR_CONTENT_DISPOSITION_VALUE
+ bean.getName() + "\"");
response.getOutputStream().write(rb, 0, rb.length);
response.getOutputStream().flush();
response.getOutputStream().close();
}
As per the Official Documentation of ckeditor we need to write the xhr code at editor level and also at server level which I am not able to get. Could you please help me out in achieving the same.

Android Java OnPageFinished doesn't work when load Javascript in WebView

I need to get a link address from a webpage that is generated by javascript clicking on a button.
I click on the link in this way
webView.loadUrl("javascript:(function(){" +
"var All = document.getElementsByTagName('img');\n" +
"for (var i = 0; i < All.length; i++) {\n" +
"if (All[i].getAttribute('title') == 'Download') {\n" +
"var imgButton=All[i];\n" +
"e=document.createEvent('HTMLEvents');\n" +
"e.initEvent('click',true,true);\n" +
"imgButton.dispatchEvent(e);\n" +
"}\n" +
"}})()");
the problem is that after running this code, the event OnPageFinished is never called. I had try with OnProgressChanged using WebChromeClient but I had the same result.
I need to obtain the html code of the webpage after that the javascript is runned Any idea about how can I do it?
webView.setWebViewClient(new WebViewClient() {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
progressDialog = new ProgressDialog(Activity.this);
progressDialog.setMessage("Loading...Please wait");
progressDialog.setCanceledOnTouchOutside(false);
progressDialog.show();
}
#Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
if (progressDialog.isShowing()) {
progressDialog.dismiss();
}
view.loadUrl("javascript:window.HTMLOUT.showHTML('<head>'+document.getElementsByTagName('html')[0].innerHTML+'</head>');");
}
#Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
Toast.makeText(getApplicationContext(), "Oh no! "+description , Toast.LENGTH_SHORT).show();
super.onReceivedError(view, errorCode, description,failingUrl);
}
});
Here is the method
#SuppressWarnings("unused")
class MyJavaScriptInterface {
private Context ctx;
MyJavaScriptInterface(Context ctx) {
this.ctx = ctx;
}
#Keep
#JavascriptInterface
public void showHTML(String html) {
try {
Log.d("html",html);
}catch (Exception e){
e.printStackTrace();
}
}
}
}

Unable to send value from Javascript file to Android Activity

I am trying to pass a value from a custom javascript file I have included after loading a URL in a webview.
I have checked this reference but it doesn't work when I am loading a website apart from a local index.html file.
Here is my activity code where I have created the Javacript Interface:
public class MainActivity extends AppCompatActivity {
public static String URL = "https://www.ornativa.com";
private WebView mWebView;
private RelativeLayout mLoader;
private Toolbar mToolbar;
JSInterface JSI = new JSInterface(this);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
createWebView();
}
#SuppressLint("SetJavaScriptEnabled")
public void createWebView(){
mWebView = (WebView)findViewById(
R.id.webView);
mToolbar = (Toolbar)findViewById(R.id.toolbar);
mToolbar.setTitle(getResources().getString(R.string.app_name)+" | "+getResources().getString(R.string.app_name_hindi));
mLoader = (RelativeLayout) findViewById(R.id.loader);
// Add javascript support to the webview
mWebView.getSettings().setJavaScriptEnabled(true);
// Enable pinch zoom controls on webview
mWebView.getSettings().setBuiltInZoomControls(false);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
if (0 != (getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE))
{ WebView.setWebContentsDebuggingEnabled(true); }
}
// Add a WebViewClient
mWebView.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url) {
// Inject CSS when page is done loading
injectCSS();
injectJS();
super.onPageFinished(view, url);
mLoader.setVisibility(View.GONE);
}
});
mWebView.addJavascriptInterface(JSI, "Android");
// Load a webpage
mWebView.loadUrl(URL);
}
public void injectCSS(){
try {
InputStream inputStream = getAssets().open("styles.css");
byte[] buffer = new byte[inputStream.available()];
inputStream.read(buffer);
inputStream.close();
String encoded = Base64.encodeToString(buffer, Base64.NO_WRAP);
mWebView.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)" +
"})()");
} catch (Exception e) {
e.printStackTrace();
}
}
private void injectJS() {
try {
InputStream inputStream = getAssets().open("script.js");
byte[] buffer = new byte[inputStream.available()];
inputStream.read(buffer);
inputStream.close();
String encoded = Base64.encodeToString(buffer, Base64.NO_WRAP);
mWebView.loadUrl("javascript:(function() {" +
"var parent = document.getElementsByTagName('head').item(0);" +
"var script = document.createElement('script');" +
"script.type = 'text/javascript';" +
"script.innerHTML = window.atob('" + encoded + "');" +
"parent.appendChild(script)" +
"})()");
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void onBackPressed() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setCancelable(false);
builder.setIcon(R.mipmap.ic_launcher);
builder.setTitle(R.string.app_name);
builder.setMessage("Do you really want to Exit?");
builder.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
//if user pressed "yes", then he is allowed to exit from application
finish();
}
});
builder.setNegativeButton("No", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
//if user select "No", just cancel this dialog and continue with app
dialog.cancel();
}
});
AlertDialog alert = builder.create();
alert.show();
}
public class JSInterface {
private Context mContext;
public JSInterface(Context c) {
mContext = c;
}
#JavascriptInterface
public void showToast(String message) {
Toast.makeText(mContext, message, Toast.LENGTH_LONG).show();
}
}
}
And this is my script.js file:
document.getElementById("aadhaarNo").type= 'tel';
var myElem = document.getElementById('actionMessages');
Android.showToast("Hello World!");
if (myElem === null) {
console.log('does not exist');
}
else{
if (myElem.classList.contains('success')){
console.log('success');
}
}
I am trying to call the function from the script file to send the value to the Toast but the Toast doesn't appear.
Change "Context" to "Activity" in class JSInterface. Check the below edited code..
public class JSInterface {
private Activity mContext;
public JSInterface(Activity c) {
mContext = c;
}
#JavascriptInterface
public void showToast(String message) {
Toast.makeText(mContext, message, Toast.LENGTH_LONG).show();
}
}

LoadUrl Javascript not loading at all

could someone please help me. I'm having difficulty with LoadUrl and javascript.
The code below seems to work sorta ok (killing the app then trying again makes it work) on my old HTC running 2.3 however, my Xperia Z which runs the latest Android gets stuck on "Attempting to get Comments".
The section of code it is sticking on is InjectJavaScript() wherein this fails to LoadUrl (I know this as onPageFinished is never called). The strange thing is statistics part of the code works fine and its identical.
Sorry its pretty messy code...
#SuppressLint("SetJavaScriptEnabled")
public class MyIceland extends SherlockActivity {
private static class FetchMyIceland extends AsyncTask<Void, Void, Void>{
#Override
protected Void doInBackground(Void... arg0) {
setDialog("Checking Farera for WoW Data....",2);
switch(FETCHFROMMYICELAND){
case 0: //contact Farera for information.
Log.i("IcePlan","Farera Check/Empathica Front Page Retrieval...");
MyIceland.url = MainActivity.BASE_URL+"android_get.php?action=myiceland&store="+MainActivity.STORE;
try {
String Result = HTTPGET();
if(Result.startsWith("no")){ //content for today?
setDialog("No WoW Data Available for Today\nAbout to contact Empathica.com....",2);
activity.runOnUiThread(new Runnable(){#Override public void run() {MyIceland.FetchFromEmpathica("http://www.iceland.empathica.com/LogonIceland.aspx");;}}); }
else{FETCHFROMMYICELAND = 100;} //we do have content...
} catch (IOException e1) {Log.i("IcePlan",e1.toString());} catch (Exception e1) {Log.i("IcePlan",e1.toString());
} //we have data for today, so download and sort it.
break;
case 1: //get comments
setDialog("About to Contact Empathica.com for Comments....",2);
try {Thread.sleep(1000);} catch (InterruptedException e) {Log.i("IcePlan",e.toString());}
activity.runOnUiThread(new Runnable(){#Override public void run() {MyIceland.FetchFromEmpathica("http://v2.empathica.com/Reporting1/ClientReporting/LiveDataReporting.aspx?RID=1&PID=Comments&TID=1a");}});
break;
case 2: //POST data
setDialog("Posting all data to Farera.com \n So we don't have to do this again today....",2);
List<NameValuePair> params = new ArrayList<NameValuePair>();
try {params.add(new BasicNameValuePair("frontpage", URLEncoder.encode(FRONTPAGE, "utf-8")));} catch (UnsupportedEncodingException e) {Log.e("IcePlan",e.toString());}
try {params.add(new BasicNameValuePair("comments", URLEncoder.encode(COMMENTS, "utf-8")));} catch (UnsupportedEncodingException e) {Log.e("IcePlan",e.toString());}
MyIceland.url = MainActivity.BASE_URL+"android_get.php?action=store_myiceland&store="+MainActivity.STORE;
String POST = HTTPPOST(params);
if(POST != null){FETCHFROMMYICELAND = 100; }
break;
}
return null;
}
#Override
protected void onPreExecute(){super.onPreExecute();}
#Override
protected void onPostExecute(Void arg0){
if(FETCHFROMMYICELAND == 100) new MyIceland.DisplayMyIceland().execute();
}
}
//------------------------------------------------------
//-----------------------------------------------------
//-----------------------------------------------------
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_iceland);
ctx = getApplicationContext();
activity = this;
//webView2 = (WebView) findViewById(R.id.myIwebview2_widget);
/********************************************************/
/****************** ABS ********************************/
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().show();
// This is a workaround for http://b.android.com/15340 from
// http://stackoverflow.com/a/5852198/132047
BitmapDrawable bg = (BitmapDrawable) getResources().getDrawable(
R.drawable.bg_striped);
bg.setTileModeXY(TileMode.REPEAT, TileMode.REPEAT);
getSupportActionBar().setBackgroundDrawable(bg);
BitmapDrawable bgSplit = (BitmapDrawable) getResources().getDrawable(
R.drawable.bg_striped);
bgSplit.setTileModeXY(TileMode.REPEAT, TileMode.REPEAT);
getSupportActionBar().setSplitBackgroundDrawable(bgSplit);
/************************************************************/
try {
ov_e = (TextView) findViewById(R.id.overall_exp_tx);
ov_r= (TextView) findViewById(R.id.overall_rank_tx);
s_e= (TextView) findViewById(R.id.storeexp_tx);
st_e= (TextView) findViewById(R.id.staffexp_tx);
t_e= (TextView) findViewById(R.id.tillexp_tx);
res= (TextView) findViewById(R.id.responses_tx);
res_r= (TextView) findViewById(R.id.resp_rank_tx);
MyIceland.list = (ListView) findViewById(R.id.wow_lv); // set list
MyIceland.adapter = new SeparatedListAdapter(ctx, false); // initialise adapter
//authenticate
CookieSyncManager.createInstance(this);
SetUp(); //Set up webView
setDialog("Loading MyIceland data...\n Please be Patient...",0);
new FetchMyIceland().execute(); //get data
} catch (Exception e) {
// TODO Auto-generated catch block
Log.i("IcePlan",e.toString());
}
}
private static String HTTPPOST(List<NameValuePair> params){
String Resp = null;
try {
HttpClient client = new DefaultHttpClient();
String postURL = MyIceland.url;
HttpPost post = new HttpPost(postURL);
//List<NameValuePair> params = new ArrayList<NameValuePair>();
//params.add(new BasicNameValuePair("user", "kris"));
UrlEncodedFormEntity ent = new UrlEncodedFormEntity(params,HTTP.UTF_8);
post.setEntity(ent);
HttpResponse responsePOST = client.execute(post);
HttpEntity resEntity = responsePOST.getEntity();
if (resEntity != null) {
Resp = "not null";
}
} catch (Exception e) {
Log.e("IcePlan HTTPPOST",e.toString());
}
return Resp;
}
private static String HTTPGET() throws Exception, IOException{
HttpClient client = new DefaultHttpClient();
HttpGet request = new HttpGet(url);
HttpResponse response = client.execute(request);
InputStream in = response.getEntity().getContent();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
StringBuilder str = new StringBuilder();
String line = null;
while((line = reader.readLine()) != null)
{
str.append(line);
}
in.close();
Log.i("IcePlan",str.toString());
return str.toString();
}
private void SetUp(){
webView = (WebView) findViewById(R.id.myIwebview_widget); //load custom webview
webView.clearView(); //clear view of browser
webView.clearFormData(); //clear form data
webView.setNetworkAvailable(MainActivity.isOnline(ctx)); //set network state
webView.getSettings().setDomStorageEnabled(true);
webView.getSettings().setPluginsEnabled(false); //no flash
webView.getSettings().setJavaScriptEnabled(true); // enable javascript
webView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
webView.addJavascriptInterface(new MyJavaScriptInterface(), "HTMLOUT");
webView.getSettings().setSavePassword(false); //don't show password dialog
webView.setVerticalScrollBarEnabled(false); //no scrolling!
webView.setHorizontalScrollBarEnabled(false); //no scrolling!
webView.getSettings().setLoadsImagesAutomatically(false); // NO Images
webView.getSettings().setSaveFormData(false); //Don't save form data
//webView.setVisibility(View.VISIBLE);
return;
}
private static void FetchFromEmpathica(String EmpathURL){
/*****************************************************
* setWebViewClient to load pages
*****************************************************
*****************************************************
*/
webView.loadUrl(EmpathURL);
MyIceland.page = 0;
webView.setWebViewClient(new WebViewClient() {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
//Log.i("IcePlan",url);
view.loadUrl(url);
return true;
}
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
Log.i("IcePlan","Starting...");
super.onPageStarted(view, url, favicon);
}
#Override
public void onPageFinished(WebView view, String url) {
Log.i("IcePlan","Loaded...");
switch(FETCHFROMMYICELAND){
case 0:
if(MyIceland.page == 0){
MyIceland.page=1;
try {Thread.sleep(500);}catch (InterruptedException e) {Log.e("IcePlan",e.toString());}
view.loadUrl("javascript: {" +
"document.forms[0].elements['userNameBox'].value = 'xxx.xxxxx';" +
"setTimeout(function(){document.forms[0].elements['passwordBox'].value = 'xxxxxxx';},300);" +
"setTimeout(function(){document.forms[0].elements['loginButton'].click();},300); };");
}else if(MyIceland.page == 1){
MyIceland.page=2;
try {Thread.sleep(1000);}catch (InterruptedException e) {Log.e("IcePlan",e.toString());}
String oAuthUrl=("v2.empathica.com");
if(url.indexOf(oAuthUrl) > -1)
{
Log.i("Contains","Auth URL");
InjectJavaScript(view);
}else{view.loadUrl("javascript:{};");}
}else if (MyIceland.page ==2){
if(MyIceland.FRONTPAGE == null){
Log.i("IcePlan","Inject");
InjectJavaScript(view);
}else{MyIceland.page=3;}
}
break;
case 1:
if(MyIceland.COMMENTS == null){
Log.i("IcePlan","Inject Comments");
InjectJavaScript(view);
}else{MyIceland.page=100;} //else end
break;
}
super.onPageFinished(view, url);
}
});
return;
}
}
private static void setDialog(final String msg, final int dothis){
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
switch(dothis){
case 0: //set up and show
if (dlg == null) {
dlg = new ProgressDialog(activity);
dlg.setTitle("Loading...");
dlg.setMessage(msg);
dlg.setCancelable(activity.isFinishing());
dlg.show();
}
break;
case 1: //remove and reset to null
if (dlg.isShowing() || dlg!=null) {
dlg.hide();
dlg = null;
}
break;
case 2:
if (dlg.isShowing() || dlg!=null) {
dlg.setMessage(msg);
}
}
}});
return;
}
/*********************************************************
* HACK - Inject Javascript to get the HTML we want!
*********************************************************/
private static void InjectJavaScript(WebView view){
switch(FETCHFROMMYICELAND){
case 0: //get front page
setDialog("Attempting to get Statistics...",2);
view.loadUrl("javascript:{" +
"var element = document.getElementById('ReportDivFPRank');"+
"if (typeof(element) != 'undefined' && element != null)"+
"{" +
"var e=document.getElementById(\"ReportDivFPCR\");"+
"var content=e.innerHTML;"+
"window.HTMLOUT.processHTML(content);"+// exists.
"}" +
"};");
break;
case 1: //get comments
setDialog("Attempting to get Comments....",2);
view.loadUrl("javascript:{" +
"var element = document.getElementById('AddNPSDetails');"+
"if (typeof(element) != 'undefined' && element != null)"+
"{" +
"var e=document.getElementById(\"_ctl1_ReportDiv\");"+
"var content=e.innerHTML;"+
"window.HTMLOUT.processHTML(content);"+// exists.
"}" +
"};");
break;
}
return;
}
/*********************************************************
* Class injected into Empathica website to get HTML
* Continues onto our controlling AsyncTask
* #author Vince
*
********************************************************/
public static class MyJavaScriptInterface
{
public void processHTML(final String html)
{
setDialog("Caught RAW data....",2);
if(html != ""){
//MyIceland.webView2.loadDataWithBaseURL("notreal/", html, "text/htm", "utf-8",null);
if(FETCHFROMMYICELAND == 0){ setDialog("Retrieved Area Statistics....",2); MyIceland.FRONTPAGE = html;}
else if(FETCHFROMMYICELAND == 1){ setDialog("Retrieved Area Comments....",2); MyIceland.COMMENTS = html;}
FETCHFROMMYICELAND++;
new MyIceland.FetchMyIceland().execute();
}
return;
}
}
}
I see that FetchFromEmpathica is going to be called again when you load the second page, and you set again a new WebViewClient() to the webview, put it on the setup() method so it is going to be called once.
Make sure that your Xperia is 4.1.2, nonetheless look what is mentioned on
Reference: JavascriptInterface methods in WebViews must now be annotated
Beginning in Android 4.2, you will now have to explicitly annotate public methods with #JavascriptInterface in order to make them accessible from hosted JavaScript. Note that this also only takes effect only if you have set your app's minSdkVersion or targetSdkVersion to 17 or higher.
Add it and import android.webkit.JavascriptInterface
So the code will be up-to-date to last versions.
#JavascriptInterface
public void processHTML(final String html)
{
//code
}

Inject external JS file in Android WebView and call it

I am trying to inject my external JS file (contained in assets dir) into WebView and call it afterwards.
This is the code I use for injecting it:
webView.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
webView.loadUrl("javascript: (function() { "
+ "var script=document.createElement('script');"
+ "script.type='text/javascript';script.src='file://android_asset/js_demo.js';"
+ "document.getElementsByTagName('head').item(0).appendChild(script);"
+ "})()");
webView.loadUrl("javascript: jsDemo()");
}
});
When I print the entire content of my WebView, I can see that script tag with src='file://android_asset/js_demo.js' is indeed inserted, but calling function jsDemo does nothing.
NOTE: Function jsDemo is contained in js_demo.js and does nothing clever, just changes some span's color. It work ok since I tested it in browser.
I am convinced I made mistake giving the path to the js file, but I am not sure how to change it in order to make it work. Any help will be appreciated.
Why not just read in the file and execute it directly via loadUrl("javascript:...)?
Here is how i ended up doing it. I used the Content:// protocol and set up a contentprovider to handle returning a file descriptor to the system
Here is my fileContentProvider:
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import org.apache.commons.io.IOUtils;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.ParcelFileDescriptor;
import android.util.Log;
public class FileContentProvider extends ContentProvider {
#Override
public ParcelFileDescriptor openFile(Uri uri, String mode) {
Log.d("FileContentProvider","fetching: " + uri);
ParcelFileDescriptor parcel = null;
String fileNameRequested = uri.getLastPathSegment();
String[] name=fileNameRequested.split("\\.");
String prefix=name[0];
String suffix=name[1];
// String path = getContext().getFilesDir().getAbsolutePath() + "/" + uri.getPath();
//String path=file:///android_asset/"+Consts.FILE_JAVASCRIPT+"
/*check if this is a javascript file*/
if(suffix.equalsIgnoreCase("js")){
InputStream is = null;
try {
is = getContext().getAssets().open("www/"+Consts.FILE_JAVASCRIPT);
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
File file = stream2file(is,prefix,suffix);
try {
parcel = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
} catch (FileNotFoundException e) {
Log.e("FileContentProvider", "uri " + uri.toString(), e);
}
}
return parcel;
}
/*converts an inputstream to a temp file*/
public File stream2file (InputStream in,String prefix,String suffix) {
File tempFile = null;
try {
tempFile = File.createTempFile(prefix, suffix);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
tempFile.deleteOnExit();
FileOutputStream out = null;
try {
out = new FileOutputStream(tempFile);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
IOUtils.copy(in, out);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return tempFile;
}
#Override
public boolean onCreate() {
return true;
}
#Override
public int delete(Uri uri, String s, String[] as) {
throw new UnsupportedOperationException("Not supported by this provider");
}
#Override
public String getType(Uri uri) {
throw new UnsupportedOperationException("Not supported by this provider");
}
#Override
public Uri insert(Uri uri, ContentValues contentvalues) {
throw new UnsupportedOperationException("Not supported by this provider");
}
#Override
public Cursor query(Uri uri, String[] as, String s, String[] as1, String s1) {
throw new UnsupportedOperationException("Not supported by this provider");
}
#Override
public int update(Uri uri, ContentValues contentvalues, String s, String[] as) {
throw new UnsupportedOperationException("Not supported by this provider");
}
}
in the manifest i defined the provider:
<provider android:name="com.example.mypackage.FileContentProvider"
android:authorities="com.example.fileprovider"
/>
Here is the javascript i inject into the webview:
webView.loadUrl("javascript:(function() { "
+ "var script=document.createElement('script'); "
+ " script.setAttribute('type','text/javascript'); "
+ " script.setAttribute('src', 'content://com.example.fileprovider/myjavascriptfile.js'); "
/* + " script.onload = function(){ "
+ " test(); "
+ " }; "
*/ + "document.body.appendChild(script); "
+ "})();");
and here is the myjavascriptfile.js (as an example):
function changeBackground(color) {
document.body.style.backgroundColor = color;
}
Thanks for the feedback guys. I tried most of the suggestions and here's how I got to inject a .js file for every webpage webkit loads.
Read a local js file to a string.
Append that string to script.text after creating a document element with type text/javascript
Call javascript: (function() { <programmatically formatted string dynamically creating webpage script element >})()" inside an overridden webview onPageFinished.
Verified working on Android 4.0.3–4.0.4 Ice Cream Sandwich (API level 15)
You need three slashes after "file:"

Categories