I am developing android application and I am trying to show loading spinner while my html is being formatted, but the spinner is not showing and I have no idea why. Here is the code:
$.mobile.loading('show');
if (window.localStorage.getItem("UserTeams") != null && manual == false) {
$(window.localStorage.getItem("UserTeams")).appendTo("#listTeams");
$("#listTeams").listview("refresh").listview();
}
$.mobile.loading('hide');
Any ideas why the spinner is not showing?
Try to use native functions via JavaSriptInterface to show progress.
JavaScriptInterface:
private final class JavaScriptInterface {
public JavaScriptInterface() {
}
/* progressDialog is a field of Your Activity.
JavaScriptInterface is internal class of Your Activity. */
public void showDialog() {
if (progressDialog != null) {
if (!progressDialog.isShowing()) {
progressDialog = ProgressDialog.show(this, "", getString(R.string.common_loading_upper));
}
}
}
public void hideDialog() {
if (progressDialog != null) {
progressDialog.dismiss();
}
}
}
Register JavaScriptInterface:
webView.addJavascriptInterface(new JavaScriptInterface(), "myinterface");
JavaScript code to call dialog:
window.myinterface.showDialog();
Related
I am creating an AppDrawer (all in one place to launch shortcuts).
My JSCallBack bridge class has a method that should delete a shortcut, then refresh the page. But, it is unable to successfully refresh the page.
AppDrawerMain.java
public class AppDrawerMain extends Application {
#Override
public void start(Stage stage) throws IOException {
FXMLLoader fxmlLoader = new FXMLLoader(AppDrawerMain.class.getResource("main.fxml"));
Parent root = (Parent) fxmlLoader.load();
Scene scene = new Scene(root, 1280, 720);
String css = this.getClass().getResource("application.css").toExternalForm();
scene.getStylesheets().add(css);
stage.setTitle("Hello!");
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
}
AppDrawerController.java
public class AppDrawerController implements Initializable {
#FXML
private Button refreshButton;
#FXML
private WebView webView;
WebEngine webEngine;
JSCallBack jsCallBack;
//this function essentially generates the html code for the webview
public String loadApps(){
return "<div class=\"container\"><img src=\"file:/"+imagePath+"\"/><p class=\"title\">"+displayName+"</p><div class=\"overlay\"></div><div class=\"button-open\" onclick=\"app.processOnClickOpen(\'"+id+"\')\"> Open </div><div class=\"button-option\" onclick=\"app.processOnClickOption(\'"+id+"\')\"> Edit </div></div>"
}
//refresh the page
private void refreshPage(String html){
webEngine.loadContent(html);
webEngine.reload();
}
#SneakyThrows
#Override
public void initialize(URL url, ResourceBundle resourceBundle) {
refreshButton.setOnAction(event -> {
refreshPage(loadApps());
});
webEngine = webView.getEngine();
webEngine.getLoadWorker().stateProperty().addListener((obs, oldValue, newValue)-> {
if (newValue == Worker.State.SUCCEEDED) {
JSObject jsObject = (JSObject) webEngine.executeScript("window");
jsCallBack = new JSCallBack(webEngine); //declared this way to avoid GC
jsObject.setMember("app", jsCallBack);
}
});
webEngine.setJavaScriptEnabled(true);
var html = loadApps();
webEngine.loadContent(html);
}
//The bridge class
public class JSCallBack {
protected JSCallBack() {}
//no refresh needed here
public void processOnClickOpen(String id) {
log("Before open");
onAppOpen(id);
log("After open");
}
//The part that isnt working
public void processOnClickOption(String id) {
//deleting the apps works fine
webEngine.loadContent(loadApps()+loadApps()); //trying to refresh the page isnt fine
webEngine.reload();
}
}
}
The problem I am having is here:
public void processOnClickOption(String id) {
//refreshPage(loadApps()+loadApps()) (not working either)
//refreshButton.fire() (not working either)
webEngine.loadContent(loadApps()+loadApps()); //trying to refresh the page isnt fine
webEngine.reload(); //not working
}
I tried adding location.reload() to the JavaScript function in the script itself, but it did not work.
I tried adding the refreshButton.fire() to the processOnClickOption(), which should reload the page if clicked on manually, but it did work either.
I tried to set a new WebEngine in the bridge class itself. Also, it did not work.
I added a log to see if there was an issue with threading, but WebEngine mentions that it was on the JavaFX Application thread, so that is not the problem either.
This is the main WebView:
If I click on the edit button, it should remove it from the WebView and refresh the page like this expected outcome:
Unfortunately, after clicking the edit button it will delete the files on the backend side, but the WebView is not refreshed, so the app stays there. I would like to get help on this.
I want to open a webpage in a WebView and click automatically on a button after the page has loaded. This is my current WebView class:
public class WebViewFragment extends Fragment {
...
#Override
public void onResume() {
super.onResume();
openUrl();
}
private void openUrl() {
setCookies();
if (urlToOpen != null) {
//tell webview to handle redirects (by default browser launches on redirects)
webview.setWebViewClient(new WebViewClient() {
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
if (getActivity() != null)
((MainActivity) getActivity()).onShowLoading();
}
#Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
if (getActivity() != null) {
executeJS();
((MainActivity) getActivity()).onHideLoading();
}
}
});
if (javascriptToExecute != null) {
webview.getSettings().setJavaScriptEnabled(true);
}
webview.loadUrl(urlToOpen);
}
}
private void executeJS() {
System.out.println("executeJS(): " + javascriptToExecute);
webview.loadUrl(javascriptToExecute);
}
}
I can use "javascript:$('#customer-info-edit').click();" or "javascript:document.getElementById('customer-info-edit').click();" both work fine.
But the problem is they work only one time. If I open the WebView for the first time, the button is clicked. However if I press physical back button and open the WebView again then the button is not clicked. Why isn't Javascript working every time?
I don't know what the problem exactly was, but I found a working solution: add 500ms delay before executing javascript.
I have added an InAppBrowser plugin into a Cordova project to access a site and get token but while the site is opening normally in desktop browsers the same is giving error while opening from mobile browser.
Also the default native browser will ask to continue in case of SSL error but the Cordova InAppBrowser is not asking for such option and instead showing an error page. I am opening the IAB using the following code :
var iab = window.open('http://www.example.com', '_blank', 'location=yes');
Any idea on how to bypass SSL erros in InAppBrowser ?
I'm going to expand on the answer to the related question (phonegap inappbrowser https pages not loading). This pertains only to Android, sorry still working on iOS.
Add this code:
public void onReceivedSslError(WebView view,
SslErrorHandler handler, SslError error) {
Log.e("Error", "Received SSL error"+ error.toString());
handler.proceed();
}
to the InAppBrower.java file from the plugin. Specifically, it should be under the InAppBrowserClient class.
Hope this helps!
Insert Proper Code from below InAppBrowser.java in to your plugin
LOCATED IN platforms\android\src\org\apache\cordova\inappbrowser\InAppBrowser.java
Filtered code from below java code:
import android.net.http.SslError;
import android.webkit.SslErrorHandler;
#SuppressLint("SetJavaScriptEnabled")
public class InAppBrowser extends CordovaPlugin {
private boolean ignoreSSLError = false;
private HashMap<String, Boolean> parseFeature(String optString) {
if (optString.equals(NULL)) {
return null;
} else {
HashMap<String, Boolean> map = new HashMap<String, Boolean>();
StringTokenizer features = new StringTokenizer(optString, ",");
StringTokenizer option;
while(features.hasMoreElements()) {
option = new StringTokenizer(features.nextToken(), "=");
if (option.hasMoreElements()) {
String key = option.nextToken();
if(key.equalsIgnoreCase(IGNORE_SSL_ERROR)) {
Boolean value = option.nextToken().equals("no") ? Boolean.FALSE : Boolean.TRUE;
map.put(key, value);
}
else {
Boolean value = option.nextToken().equals("no") ? Boolean.FALSE : Boolean.TRUE;
map.put(key, value);
}
}
}
return map;
}
}
public String showWebPage(final String url, HashMap<String, Boolean> features) {
// Determine if we should hide the location bar.
showLocationBar = true;
showZoomControls = true;
openWindowHidden = false;
ignoreSSLError = false;
if (features != null) {
Boolean show = features.get(LOCATION);
if (show != null) {
showLocationBar = show.booleanValue();
}
Boolean SSLError = features.get(IGNORE_SSL_ERROR);
if(SSLError != null){
ignoreSSLError = SSLError.booleanValue();
}
Boolean zoom = features.get(ZOOM);
if (zoom != null) {
showZoomControls = zoom.booleanValue();
}
Boolean hidden = features.get(HIDDEN);
if (hidden != null) {
openWindowHidden = hidden.booleanValue();
}
Boolean hardwareBack = features.get(HARDWARE_BACK_BUTTON);
if (hardwareBack != null) {
hadwareBackButton = hardwareBack.booleanValue();
}
Boolean cache = features.get(CLEAR_ALL_CACHE);
if (cache != null) {
clearAllCache = cache.booleanValue();
} else {
cache = features.get(CLEAR_SESSION_CACHE);
if (cache != null) {
clearSessionCache = cache.booleanValue();
}
}
}
#SuppressLint("NewApi")
public void run() {
((InAppBrowserClient) client).setSSLErrorFlag(ignoreSSLError);
}
};
this.cordova.getActivity().runOnUiThread(runnable);
return "";
}
public class InAppBrowserClient extends WebViewClient {
EditText edittext;
CordovaWebView webView;
boolean ignoreSSLError = false;
#Override
public void onReceivedSslError(WebView view, SslErrorHandler handler,
SslError error) {
if(this.ignoreSSLError) {
handler.proceed();
return;
}
else{
super.onReceivedSslError(view, handler, error);
}
}
public void setSSLErrorFlag(boolean flag) {
this.ignoreSSLError = flag;
}
}
}
THEN ADD THIS LINE IN JAVASCRIPT
var options = {
location: 'yes',
//clearcache: 'no',
toolbar: 'yes',
//clearsessioncache:'no',
zoom:'no',
ignoresslerror:'yes'
};
$scope.init = function () {
$ionicPlatform.ready(function() {
$cordovaInAppBrowser.open('https://192.168.1.80', '_blank', options)
.then(function(event) {
})
.catch(function(event) {
});
});
AFTER DONE THIS COMPILE AND EXECUTE THAT'S IT
FULL VERSION CODE
Local https links are blocked by default in InAppBrowser (links using fake SSL certificate which can't be verified by a 3rd party). Ideally, user should be given an option to proceed or cancel the request like the default desktop browsers do.
Right now, we have to additional method for accessing fake ssl in the InAppBrowser like location,zoom,hardwareback
In my Android web app I am trying to use javascript (from a remote HTML file) to control the visibility of an Android WebView.
I have attempted to use the addJavascriptInterface class with no success. (see http://developer.android.com/guide/webapps/webview.html)
Essentially I would like my javascript to be the following
<script>
function this() {
Android.hideView('myWebViewID');
}
window.onload = this;
</script>
Seems like it would be easy, yet all my attempts cause my app to crash during debugging.
My latest attempt was something along these lines:
public class JavaScriptInterface {
Context mContext;
JavaScriptInterface(Context c) {
mContext = c;
}
public void hideView(View v) {
WebView webview_x = (WebView) v;
webview_x.setVisibility(View.GONE);
}
}
The problem is that you are casting the string "myWebViewID" in a WebView object.
I guess this is impossible.
To do what you want, you have to implement something like a switch that convert the string you use in JS to an ID (int) that identifies your WebView:
public class JavaScriptInterface {
private Activity mContext;
JavaScriptInterface(Activity c) {
mContext = c;
}
public void hideView(String v) {
int id = stringToId(v);
WebView webview_x = (WebView) mContext.findViewById(id);
webview_x.setVisibility(View.GONE);
}
private Integer stringToId(String str) {
if(str.equals("stringForId1") {
return R.id.webView1;
} else if(str.equals("stringForId2") {
return R.id.webView2;
} else if(...) {
....
} else {
return null;
}
}
}
This is the solution:
WebView:
mWebView = (WebView) findViewById(R.id.webview);
mWebView.setWebChromeClient(new CustomWebChromeClient());
mWebView.addJavascriptInterface(new CustomJavaScriptInterface(),
"android");
mWebView.loadUrl("file:///android_asset/www/test.html");
CustomeJavascriptInterface:
final class CustomJavaScriptInterface {
public void hide() {
mHandler.post(new Runnable() {
public void run() {
mWebView.setVisibility(View.INVISIBLE);
}
});
}
}
HTML:
<div onclick="window.android.hide()">Click!</div>
You should be fine with this!
Note that you cannot access the webview and change its visibility without a handler!
Hope this helps!
final Context myApp = this;
/* An instance of this class will be registered as a JavaScript interface */
class MyJavaScriptInterface
{
#SuppressWarnings("unused")
public void showHTML(String html)
{
new AlertDialog.Builder(myApp)
.setTitle("HTML")
.setMessage(html)
.setPositiveButton(android.R.string.ok, null)
.setCancelable(false)
.create()
.show();
}
}
final WebView browser = (WebView)findViewById(R.id.browser);
/* JavaScript must be enabled if you want it to work, obviously */
browser.getSettings().setJavaScriptEnabled(true);
/* Register a new JavaScript interface called HTMLOUT */
browser.addJavascriptInterface(new MyJavaScriptInterface(), "HTMLOUT");
/* WebViewClient must be set BEFORE calling loadUrl! */
browser.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url)
{
/* This call inject JavaScript into the page which just finished loading. */
browser.loadUrl("javascript:window.HTMLOUT.showHTML(''+document.getElementsByTagName('html')[0].innerHTML+'');");
}
});
/* load a web page */
browser.loadUrl("http://lexandera.com/files/jsexamples/gethtml.html");
In to the above code after
new AlertDialog.Builder(myApp)
.setTitle("HTML")
.setMessage(html)
.setPositiveButton(android.R.string.ok, null)
.setCancelable(false)
.create()
.show();
I want to set visibility of the button true and false but it gives me error does any one have any idea why its happens and have any solution?
Thanks in advance
Finally I got the solution of the error. I'm using:
btn.post(new Runnable() {
#Override
public void run() {
btn.requestFocus();
btn.setVisibility(0);
}
}
And after that I'm starting a new thread when I want to show the button