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
Related
I've been developing an Android app for my business for a long time and it's been working fine, using a webview and calling back and forth between native features. In case it's relevant, here's the Java entry point to my app:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRequestedOrientation (ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
setContentView(R.layout.activity_main);
myWebView = (WebView) findViewById(R.id.webview);
final Context that = this;
myWebView.addJavascriptInterface(new WebAppInterface(this, this), "Android");
myWebView.setWebViewClient(new WebViewClient(){
public void onPageFinished(WebView view, String url) {
myWebView.evaluateJavascript("pageFinished()", null);
}
});
pm = this.getPackageManager();
WebSettings webSettings = myWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setAllowUniversalAccessFromFileURLs(true);
webSettings.setDomStorageEnabled(true);
WebView.setWebContentsDebuggingEnabled(true);
Window window = getWindow();
//window.setStatusBarColor(Color.parseColor("#3596d4"));
myWebView.loadUrl("file:///android_asset/index.html");
IntentFilter filter = new IntentFilter();
filter.addCategory(Intent.CATEGORY_DEFAULT);
filter.addAction(getResources().getString(R.string.activity_intent_filter_action));
registerReceiver(myBroadcastReceiver, filter);
mDetector = new GestureDetectorCompat(that, this);
myWebView.setOnTouchListener(touchListener);
}
Now when I set the minimum version to 18 in my gradle file, some lines got marked by Android Studio as 'not supported by API 18', most notably my myWebView.evaluateJavascript calls, but also some other stuff like WebView.setWebContentsDebuggingEnabled.
How can I do evaluateJavascript in API 18?
Also in some places, when I call evaluateJavascript, I expect a response back, for example:
myWebView.evaluateJavascript("Back.go()", new ValueCallback<String>() {
#Override
public void onReceiveValue(String canGoBack) {
if (canGoBack.equals("false")) {
moveTaskToBack(true);
} else {
// don't need to do anything, already called Back.go()
// that means the javascript already handled navigation
}
}
});
Will that be possible with API 18?
How can I do evaluateJavascript in API 18?
Use loadUrl("javascript:..."), where the...` is your JavaScript code.
Will that be possible with API 18?
No, sorry. The closest thing is to have your JavaScript code call something on your WebAppInterface that you injected via addJavascriptInterface().
Note that at the present time only ~4% of Android devices using the Play Store are running API Level 18 or older.
I'm a beginner at android.
I used javascript method in android. And I want to call it when the app is loaded for first time.
For example,
testMethod = function(str) {
alert("hi" + str);
}//javascript
and
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.getSettings().setDefaultTextEncodingName("utf-8");
mWebView.loadUrl("file:///index.html");
mWebView.addJavascriptInterface(androidBridge, "jsinterface");
mWebView.loadUrl("javascript:testMethod('javascript')");
}
What I was thinking here is the alert will pop up immediately when I start the app.
But nothing happens.
About this, I have two questions.
1.Can I call and use the javascript method in Android's onCreate method?
2.If it is possible, How can I do?
if you want to show a popup on start just use the default AlertDialog. see the code below.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
showMessage("My Message Here", "Title here");
}
private void showMessage(String data, String title){
new AlertDialog.Builder(this)
.setTitle(title)
.setMessage(data)
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// continue
}
})
.show();
}
check out whether index.html is REALLY loaded. I guess that webview didn't load your html properly, bcz it's not an invalid file path. try file:///mnt/sdcard/index.html. (or something likely)
try to put mWebView.loadUrl("javascript:testMethod('javascript')") in view.post or view.postDelayed.
Frustration has finally overcome me and I am reaching out for some assistance. Currently in my app I have a webview that loads a series of pages. On several of the pages there are JS Login popups that appear. If I use a WebChromeClient and just straight open the browser the pages work fine however in my webview I cannot for my life get the popups to appear. I have tried a custom ChromeClient to handle the JS popups. I have also tried dozens of questions and answers on SO to no avail. Essentially is there any way to get the straight functionality of the WebChromeClient but keep it in my fragments webview. Any help would be absurdly appreciated.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.activity_m2_web, container, false);
web = (WebView) rootView.findViewById(R.id.m2webView);
web.getSettings().setJavaScriptEnabled(true);
web.getSettings().setLoadWithOverviewMode(true);
web.getSettings().setUseWideViewPort(true);
web.setWebViewClient(new WebViewController());
web.setWebChromeClient(new WebChromeClient());
web.getSettings().setAllowFileAccess(true);
web.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
web.getSettings().setLoadWithOverviewMode(true);
web.getSettings().setUseWideViewPort(true);
web.getSettings().setDomStorageEnabled(true);
web.loadUrl("myurl");
web.setOnKeyListener(new View.OnKeyListener() {
public boolean onKey(View v, int keyCode, KeyEvent event) {
if ((keyCode == KeyEvent.KEYCODE_BACK) && web.canGoBack()) {
web.goBack();
return true;
}
return false;
}
});
return rootView;
}
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;
}
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()).