interact with website using android webview - javascript

I run a forum which has a shoutbox plugin installed where users can talk to each other just like instant messaging. I decided to make what i thought would be a quick app which would just display the shoutbox so users could talk while on the go instead of using there browser. The problem i have found is that it all works great using android webview but when you try and send a shout it comes up with an error saying "fail!" as though it has no communication with the actual shoutbox.
My question is can webview be used like this or can it only be used to display a webpage with out actually interacting with it? Below is my code what i am using so you guys can see if i am missing anything and if so please point me in the right direction thanks.
public class splash extends Activity {
WebView mWebView;
#Override
public void onCreate(Bundle savedInstanceState)
{
final Activity mActivity = this;
super.onCreate(savedInstanceState);
// Adds Progrss bar Support
this.getWindow().requestFeature(Window.FEATURE_PROGRESS);
setContentView(R.layout.mainx);
// Makes Progress bar Visible
getWindow().setFeatureInt( Window.FEATURE_PROGRESS, Window.PROGRESS_VISIBILITY_ON);
mWebView = (WebView) findViewById( R.id.webview);
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.loadUrl("http://www.myforum.com/forums/shoutbox.php");
mWebView.setWebChromeClient(new WebChromeClient()
{
public void onProgressChanged(WebView view, int progress)
{
//Make the bar disappear after URL is loaded, and changes string to Loading...
mActivity .setTitle("Loading...");
mActivity .setProgress(progress * 100); //Make the bar disappear after URL is loaded
// Return the app name after finish loading
if(progress == 100)
{
setTitle(R.string.title);
}
}
});
}
}

Creating and setting a
WebViewClient
subclass. It will be called when things happen that impact the rendering of the content, eg, errors or form submissions. You can also intercept URL loading here (via shouldOverrideUrlLoading()).

Related

Android WebView crash using local web page

Can a webview in an android application crash due to errors in client side webpage. I tried loading a local webpage into the webview and crash that by throwing javascript errors and brute force attacks but the webview/app dint crash. I am working on a project which does analysis of the crashes(number of crashes etc.) by an apk.
JUST TELLING HOW TO CRASH A WEB-VIEW IN ANDROID APP WOULD BE REALLY HELPFUL, IRRESPECTIVE OF THE JAVA CODE BELOW.(Crashing should not done by throwing exception on some webview event. Basically, not from java.)
Following is the code I added in local webpage :
function myCrashFun() {
for(var i=0; i===i; i++) { Console.log("Hello123"); } //brute force attack
var num=1;
num.toUpperCase(); //typeError
}
</script><br>
<button type="button" onclick="myFunction()">Click Me!</button><br>
<button type="button" onclick="myCrashFun()">Click to crash!</button>
following is the code for webview activity using hello.html local webage :
public class WebviewTest extends Activity
{
WebView wv;
#Override
public void onBackPressed()
{
if (wv.canGoBack()) {
wv.goBack();
}
else {
super.onBackPressed();
}
}
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_webview_test);
wv = (WebView) findViewById(R.id.wv1);
//If the web page you plan to load in your WebView use JavaScript, you must enable JavaScript for your WebView.
wv.getSettings().setJavaScriptEnabled(true);
wv.setFocusable(true);
wv.setFocusableInTouchMode(true);
//WebSettings provides access to a variety of other settings that you might find useful.
wv.getSettings().setRenderPriority(WebSettings.RenderPriority.HIGH);
wv.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
wv.getSettings().setDomStorageEnabled(true);
wv.getSettings().setDatabaseEnabled(true);
wv.getSettings().setAppCacheEnabled(true);
wv.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
wv.loadUrl("file:///android_asset/hello.html");
wv.setWebViewClient(new WebViewClient());
}
}
I don't want a webview to crash by throwing java exception/error. That part is already handled. Is there any way to crash the web view, using javascript or some client side technology..

webView loadURL not working on HTML button click

I have a webView in my application. The webView initially opens an HTML page I created with a few buttons on it. The buttons do various tasks (I'm trying to learn how to use webViews) like: 1)show android toast, 2)show javascript alert, 3)vibrate phone, 4)show current geolocation, 5)open google maps in webView.
It's this last one that's not working. I've searched this site and many others, but haven't found a solution that works.
I'm fairly certain I have all the manifest file 'stuff' correct (everything else is working, including the initial internet based web page). I'm happy to post that too though if you think it's needed.
My activity_main.xml file has never given me issues, but again, I'm happy to post that if you think it'll help.
Here are snippets from my code:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myWebView = (WebView) findViewById(R.id.webView);
myWebView.loadUrl(url); // this one works
myWebView.setWebViewClient(new MyWebViewClient());
WebSettings webSettings = myWebView.getSettings();
webSettings.setBuiltInZoomControls(true);
webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
webSettings.setJavaScriptEnabled(true);
webSettings.setGeolocationEnabled(true);
...
}
That all works and again the other html buttons work.
Then there's this:
public class WebAppInterface {
Context mContext;
//** Instantiate the interface and set the context *//
WebAppInterface(Context c) {
mContext = c;
}
//** Show a toast from the web page */
#JavascriptInterface
public void showToast(String toast) {
Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show();
}
#JavascriptInterface
public void vibrateDevice() {
Vibrator mVibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
mVibrator.vibrate(500);
}
#JavascriptInterface
public void showMapCurPos() {
new Handler().post(new Runnable() {
String url2 = "http://www.google.com/maps/#53.001153,-95.0752916,15z";
#Override
public void run() {
myWebView.clearCache(true);//Here you call the methond in UI thread
myWebView.loadUrl(url2);
}
});
}
}
Everything works there, except for showMapCurPos(). I've already tried just a simple myWebView.loadUrl(...) along with several attempts at intents. Depending on what I've tried, sometimes that method crashes the app, but most of the time the new URL just doesn't get displayed and it stays on the original URL.
Please forgive me if this is a repeat question, but I really have searched this site and many others for an answer (probably for a solid 8 hours or so). I've tried many of those answers to no avail. I'm guessing it's something simple and has to do with my lack of understanding of webViews or activities or intents or all three or maybe even my newness to android development.
I can't write a comment yet, so I'm writing this as an answer.
You could try this answer:
myWebView.post(new Runnable() {...});
instead of using new Handler

Running Javascript in Android WebView - onPageFinished Loop

I am having a bit of trouble getting my application to correctly run some JS on a page using the onPageFinished method.
The code below is contained within a class I've created that extends AsyncTask to fetch and parse a JSON file held elsewhere.
I am able to fetch the JSON file correctly, parse the data and the url for the WebView is obtained and set. Everything works loads as it should until I attempt to run some JS with the onPageFinished method.
//onPostExecute method runs when the doInBackground method is completed
#SuppressLint("SetJavaScriptEnabled")
#Override
protected void onPostExecute(Boolean aBoolean) {
super.onPostExecute(aBoolean);
//Casting as WebView as findViewById doesnt explicity return a value type.
webView = (WebView) findViewById(R.id.webView);
//Obtaining the websettings of the webView
WebSettings webViewSettings = webView.getSettings();
//Setting Javascript enabled
webViewSettings.setJavaScriptEnabled(true);
webView.setWebViewClient(new webViewClient(){
#Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
webView.loadUrl("document.getElementById('field_133').value = 'Test';");
Log.d("onPageFinished", "The Page has finished loading");
}
});
//Obtaining the first item in the cellRef List Array - From here we will access the Url data for the train operator.
parsedUrl = cellRef.get(0).getUrl();
//load the page we parsed from online file
webView.loadUrl(parsedUrl);
Log.d("loadUrl", "Now load the parsed Url");
}
All I am looking to do at the moment is test that the JS can correctly populate a textbox once the page has loaded with the value of "Test" - However, the WebView appears to be stuck in a loop of loading & refreshing (seeing repeated logcat prints of "The page has finished loading") when trying to run:
webView.loadUrl("document.getElementById('field_133').value = 'Test';");
Is this the correct way of trying to inject some JS into the WebView in Android? Apologies if there is something obvious missing, the majority of my experience lies in Swift.
Any help would be appreciated.
Thanks
Try "javascript:" before the code.
I use this, works perfectly:
loadUrl("javascript:(function() { document.getElementsByTagName('video')[0].play(); })()");

Calling JavascriptInterface method through the WebView and JS function after changing config often doesnt work

I have some problem with calling a JavaScript function in a WebView and getting response in the app (on my Galaxy Tab 2 '10). I call the js-function directly after content loading. According this one solution i use a PictureListener
webView.setPictureListener(new PictureListener() {
#Override
public void onNewPicture(WebView view, Picture picture) {
webView.loadUrl("javascript: JsImpl.init('{response}');");
}
});
it works fine: when content is loaded, onNewPicture always is started.
"javascript: JsImpl.init('{response}') loads js that calls:
class JsImpl {
private final static String LOG_TAG = "JsImpl";
#JavascriptInterface
public void init(String json) {
Log.d(LOG_TAG, json);
}
}
In the log i see D/JsImpl(18400): {response}. It seems to be everything okay but...
When I switch my tab on a landscape or portrait mode the WebView is recreated, onNewPicture are started but the method public void init(String json) in the JsImpl is often not called at all!
So if i change orientation, sometimes js works, sometimes doesn't work. No exception, no errors...
Who faced with the same problem?
Below is full code
public class NextActivity extends Activity {
#SuppressLint("SetJavaScriptEnabled")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_next);
final WebView wv = (WebView) findViewById(R.id.WebView);
wv.getSettings().setJavaScriptEnabled(true);
wv.loadUrl("file:///android_asset/index.html");
wv.addJavascriptInterface(new JsImpl(), "JsImpl");
wv.setPictureListener(new PictureListener() {
#Override
public void onNewPicture(WebView view, Picture picture) {
wv.loadUrl("javascript: JsImpl.init('{responce}');");
}
});
}
class JsImpl {
private final static String LOG_TAG = "JsImpl";
#JavascriptInterface
public void init(String json) {
Log.d(LOG_TAG, json);
}
}
}
html code is not needed here, just put on the assets dir an empty html file index.html.
EDIT:
I've found one soution but i dont know exactly is it correct varion. But it works.
I added handler loop
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
if (isJSSetup) return;
Log.i("handler-loop", "JS didn't handle. Reload page");
wv.loadUrl(CONTENT_PAGE);
handler.postDelayed(this, 1000);
}
}, 1000);
when #JavascriptInterface init(String json) is called, isJSSetup became true. In handler loop i check if JS is setup or no if (isJSSetup) return;. If no - i reload URL again wv.loadUrl(CONTENT_PAGE) and try to call init(String json). So long as it is not going to work. It's hardcode, so i'm still looking for a good solution.
I hope this will help, but I can't say for sure because you are not showing how your WebView is restored after orientation changes.
I was having very hard time making my nested fragments to work properly after orientation changes. I wanted to retain the form values and all functionality during screen rotations. It all worked fine except the JavascriptInterface was NEVER working after orientation changes.
My WebView is restored in the onCreateView. I had to remove the restoreState call for my WebView and it all works now.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.layoutT4, container, false);
webView = (WebView) rootView.findViewById(R.id.webViewT4);
prepareBrowser(); // the browser is initiated here including the JavascriptInterface
if (webView != null) {
String URL = (savedInstanceState == null) ? "" : savedInstanceState.getString("URL");
if (URL.equals("")) {
webView.loadUrl("yourhome.html");
} else {
//webView.restoreState(savedInstanceState.getBundle("webViewBundle")); // this line was preventing the JavascriptInterface to work properly
webView.loadUrl(URL); // this is saved in onSaveInstanceState - I just reopen the URL here, the PHP page will take care of reloading the data
}
}
return rootView;
}

Android webview "location.replace" doesn't work

I have an Android webview with a page that redirects to another page, using location.replace(url).
Lets say that I have page "A" that redirects to page "B" (using location.replace). When pressing "back" button from page "B", the page returns to page "A", which redirects it to page "B" again.
When I debug the history api (history.length), I can clearly see that on page "B" the length has incremented in "1" (only on Android 4.X webview. On iOS / web browser / Android 2.X it remains the same), which is a bug! (location.replace shouldn't change history.lenght!)
I work with Yaniv on this project and we found the cause of the problem, it was introduced when we tried to add mailto: links handling according to this answer.
The answer suggested using the following extending class of WebViewClient:
public class MyWebViewClient extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if(MailTo.isMailTo(url)){
MailTo mt = MailTo.parse(url);
// build intent and start new activity
return true;
}
else {
view.loadUrl(url);
return true;
}
}
}
The problem was that explicitly telling the WebViewClient to load the URL and returning true (meaning "we handled this") added the page to the history. WebViews are quite capable of handling regular URLs by themselves, so returning false and not touching the view instance will let the WebView load the page and handle it as it should.
So:
public class MyWebViewClient extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if(MailTo.isMailTo(url)){
MailTo mt = MailTo.parse(url);
// build intent and start new activity
return true;
}
else {
return false;
}
}
}
function locationReplace(url){
if(history.replaceState){
history.replaceState(null, document.title, url);
history.go(0);
}else{
location.replace(url);
}
}
Try this way..
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
WebView mainWebView = (WebView) findViewById(R.id.webView1);
WebSettings webSettings = mainWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
mainWebView.setWebViewClient(new MyCustomWebViewClient());
mainWebView.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
mainWebView.loadUrl("file:///android_asset/www/A.html");
}
Or get help from this and this link

Categories

Resources