In my onCreate method Im creating an webView and then loading an HTML file thats saved in my assets folder. This is all working fine. When a button is pressed it sends a call using javascript to this method to open the qr code scanner.
webView.setWebViewClient(new WebViewClient()
{
/* On Android 1.1 shouldOverrideUrlLoading() will be called every time the user clicks a link,
* but on Android 1.5 it will be called for every page load, even if it was caused by calling loadUrl()! */
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url)
{
System.out.println(url);
if (url.equals("fake://qr_scan"))
{
launchQRScanner(view);
}
return false;
}
});
Here is the method launchQRScanner()
public void launchQRScanner(View v) {
if (isCameraAvailable()) {
Intent intent = new Intent(this, ZBarScannerActivity.class);
intent.putExtra(ZBarConstants.SCAN_MODES, new int[]{Symbol.QRCODE});
startActivityForResult(intent, ZBAR_SCANNER_REQUEST);
} else {
Toast.makeText(this, "Rear Facing Camera Unavailable", Toast.LENGTH_SHORT).show();
}
}
So this works for the first time the button is pressed. The qr code reader open as an intent, it scans, disappears and returns the value correctly. But for every time after the method shouldOverrideUrlLoading() doesn't get called when the button is pressed. Possibly has something to do with leaving the app and coming back? Can't seem to figure it out.
BTW this is the project that I used to implement the qr code reader
https://github.com/DushyanthMaguluru/ZBarScanner
Fixed, Just had to reload the webView after the barcode is scanned. Simple fix.
Related
I have an app with a WebView which loads a list of phone numbers. In some devices, users can't make the call when clicking the phone number.
There are two pages, Page A and Page B. When I load Page A, the user can make the call, but on the same device, if they load Page B, they can't make the call.
I have checked loading both pages from mobile web browsers and web browser from PC. In both cases both A and B work fine. If this is because of something wrong with my WebView setup, user can't make the call from page A, but the user can.
I have no idea what's going on.
shouldOverrideUrlLoading
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.startsWith("tel:")) {
makePhoneCall(url);
return true;
}
return false;
}
makePhoneCall()
public void makePhoneCall(String phoneNumber) {
if (ContextCompat.checkSelfPermission(MainActivity.this,
Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.CALL_PHONE}, REQUEST_CALL);
checkPermissions();
} else {
startActivity(new Intent(Intent.ACTION_CALL, Uri.parse(phoneNumber)));
}
}
In some devices, users can't make the call when clicking the phone number
It is because you do not ask runtime permission for ACTION_CALL in Android 6 and above
Try using ACTION_DIAL instead, ACTION_CALL is for making phone call instantly and this is now restricted by Google new SMS and Call policy!
startActivity(new Intent(Intent.ACTION_DIAL, uri));
Is there a way to launch the Square POS Android app from Xamarin.Forms? I noticed all the SDK examples are in Java. Does the app have to be written using Java?
EDIT: Update
I created Bindings library in Visual Studio using the square android SDK aar file. Now, it launches the Point-of-Sale app but then it afterwords no result data is being sent back to the application. Instead, it goes to an error screen where it says "Webpage not available"
The webpage at
intent#intent;action=com.squareup.pos.action.CHARGE (more..)
could not be loaded because
net: ERROR_UNKNOWN_URL_SCHEME
I am trying to do this in a WebView by overriding ShouldOverrideUrlLoading
public override bool ShouldOverrideUrlLoading(WebView view, string url)
{
if (url.StartsWith("http:") || url.StartsWith("https:"))
{
view.LoadUrl(url);
return false;
}
if (url.Contains("CHARGE"))
{
// Process Square Point-Of-Sale Transaction
ChargeRequest chargeRequest =
new ChargeRequest.Builder(1, CurrencyCode.Usd)
.Note("Test")
.RequestMetadata("WEB_CALLBACK_URI=mycallbackurl")
.RestrictTendersTo(ChargeRequest.TenderType.Card, ChargeRequest.TenderType.CardOnFile, ChargeRequest.TenderType.Cash)
.CustomerId("MyCustomerID")
.Build();
try
{
if (PosClient == null)
{
new AlertDialog.Builder(this.activity).SetMessage("Square Point-Of-Sale Client Error").Show();
}
Intent chargeIntent = PosClient.CreateChargeIntent(chargeRequest);
this.activity.StartActivityForResult(chargeIntent, CHARGE_REQUEST_CODE);
}
catch (ActivityNotFoundException e)
{
new AlertDialog.Builder(this.activity).SetMessage(e.Message).Show();
}
}
return false;
}
EDIT: Update
I added an override for OnRecieveError
The errorCode is
Android.Webkit.ClientError.Unsupported Scheme
In the Webview Object there's this
Java.Lang.NoSuchMethodError: no non-static method
"Landroid/webkit/WebView;.getRendererPriorityWaivedWhenNotVisible()Z"
Java.Lang.NoSuchMethodError: no non-static method
"Landroid/webkit/WebView;.getRendererRequestedPriority()I"
EDIT: Update
I have it sort of working now. In the ShouldOverrideUrlLoading method, I changed it to return true if it was processing a transaction. I also had to override OnActivityResult and parse the data coming back from the Android app. It now launches the Square POS App and Returns data back to the calling app. Now, I just have figure out how to process the transaction from there.
Edit: Strangely works when duplicating the loadUrl() line
I'm working with WebViews to gather data from a webpage. Sometimes, the webview just does nothing. I tried many proposes, but actually, none of them works....
Strange: webview.loadUrl("url...") doesn't work, but as soon as I call it twice, it works...
checkLogin()
void checkLogin(final Context context) {
Log.d("checkLogin()", "Begin of checkLogin()");
WebView webview = returnNewWebView(context, false);
webview.setWebViewClient(new WebViewClient(){
#Override
public void onPageFinished(WebView view, String url) {
Log.d("url", url);
// GOOGLE.COM ACTUALLY WORKS!
if(url.equals("https://www.google.com/"))
return;
Log.d("checkLogin()", "Loading of checkpage finished");
if(url.contains("loginto.php")) {
Log.d("checkLogin()", "User is logged out");
OnLoginCheckListener.onLoginCheckLoggedOut();
} else {
Log.d("checkLogin()", "User is logged in");
OnLoginCheckListener.onLoginCheckLoggedIn();
}
}
});
String id = sharedPref.getString("id", null);
String transid = sharedPref.getString("transid", null);
if(TextUtils.isEmpty("id") || TextUtils.isEmpty("transid")) {
Log.d("checkLogin()", "No login found, starting LoginActivity()");
Intent myIntent = new Intent(context, LoginActivity.class);
context.startActivity(myIntent);
} else {
Log.d("checkLogin()", "Probably logged in, checking by loading startpage");
webview.loadUrl("https://www.google.com");
// google actually works -.-
webview.loadUrl("https://my.login-page.com/index.php?pageid=1&id=" + id + "&transid=" + transid);
}
}
returnNewWebView()
private WebView returnNewWebView(Context context, Boolean JSInterface) {
// Prepare a webview
WebView WebView = new WebView(context);
if(JSInterface) {
WebView.getSettings().setJavaScriptEnabled(true);
WebView.addJavascriptInterface(new JavaScriptInterface(), "AndroidInterface");
}
// We don't need images for data scraping...
WebView.getSettings().setLoadsImagesAutomatically(false);
WebView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
// Allow cookies
CookieManager.getInstance().acceptCookie();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
CookieManager.getInstance().acceptThirdPartyCookies(WebView);
}
// Prevent webview not loading
// or try it...
WebView.clearCache(true);
WebView.destroyDrawingCache();
return WebView;
}
As you see, I already tried some stuff in order to prevent it but still, it doesn't work. In that cases, as soon I'm going to put the loadUrl() / postUrl()twice, it works.
What can I do that it works in every single case?
I would appreciate any tip!
Thank you very much in advance
logcat (non-filtered)
I actually see this message then..
03-09 07:36:19.061 4111-24251/? E/ctxmgr: [ProducerActiveIntervalImpl]closeActiveInterval: Error: ongoing, trying to close
and this one:
03-09 07:36:28.864 29862-3249/? E/accs.GcmPush: initializeApp occur error!
java.lang.IllegalStateException: FirebaseApp name [DEFAULT] already exists!
at iv.a(Unknown Source)
at com.google.firebase.FirebaseApp.a(Unknown Source)
at com.google.firebase.FirebaseApp.a(Unknown Source)
at org.android.agoo.gcm.GcmRegister$1.run(GcmRegister.java:32)
and this one too:
E/libEGL: validate_display:99 error 3008 (EGL_BAD_DISPLAY)
But I can't tell you if they are fired by the app....
I have gone through the full code for so long and pointed out this :
You are using this -
webview.loadUrl("https://www.google.com");
// google actually works -.-
webview.loadUrl("https://my.login-page.com/index.php?pageid=1&id=" + id + "&transid=" + transid);
in your checkLogin() method which is simply wrong as because one webview can not display the two urls at same time (as you mentioned it you want to achieve that).
Now according to your code the loading of the first url is overridden by the second url.
In order to achieve the loading of two urls in same webview try to implement this using :
Threads or some sessionTimeout methods.
OR
You can achieve this by using okhttp package.
Hope this helps!
onPageFinished is called when the webpage finished loading, but not after all the javascript on the page finished running. Depending on what the page is doing and what you are trying to achieve, it might be that your code is sometimes being executed before some essential javascript is executed on that page.
It's not a pretty solution but try adding some delay (like a Handler's postDelayed() or SystemClock.sleep() - but never on the UI thread!) to your code to see if that is indeed your problem.
I've been developing hybrid apps for many companies with mobile websites.
And as a matter of fact, there are some websites made with using jsp.
I already had the knowledge that iframes and javascripts xhr requests will not fire webViewClient's shouldOverrideUrlLoading override function. I'm fine with that.
But today I learned that SOME actions such as:
JSP Page Redirects
Link Clicks within a JSP page
JSP/JS induced URL Loads
will not ALWAYS fire this function.
Hence, shouldOverrideUrlLoading() does not fire, when the webView is asked to load a page that it cannot load(i.e. "intent://...",) it shows an error page.
Has anyone encountered this kind of behaviour and is there any solution to work around it ?
Below is the code I'm using to invoke activities, where urls with 'intent:' protocol (which will fail because this function never gets called when above actions are performed)
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// ... omitted ...
if ( url.startsWith("intent:") ) {
Intent intent = null;
try {
intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME);
// The following flags launch the app outside the current app
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
try {
getActivity().startActivity(intent);
} catch (ActivityNotFoundException e) {
e.printStackTrace();
}
} catch (URISyntaxException e) {
e.printStackTrace();
}
return true;
}
}
ps. please notice that every other websites' page loads will perfectly call shouldOverrideUrlLoading().
I couldn't find any JSP related bugs on android webViews so I'm asking one.
ps. I am happily willing to provide sample websites that some gracious readers will try on.. but the website's written in Korean so I doubt it will help.
Thank you!
Your problem might not related to JSP, the real problem may be shouldOverrideUrlLoading() itself. In this case, using shouldOverrideUrlLoading() may not be a good idea, so why not try another perspective?
I've encountered many problems when using
shouldOverrideUrlLoading() loading XmlHttpRequest. At the end, I
came up with the idea using onProgressChanged() and it solved all
my problems. I've written a similar answer here.
I tried adding your code into my own webview project and tested it with some JSP sites, and looks like it always work. I also added loadUrl() after other activities are invoked, so after pressing the back button, the loading error page will not be displayed again. So try this one :
First declare a global variable to store last URL.
String strLastUrl = null;
Then override onProgressChanged(WebView view, int progress)
mWebView.setWebChromeClient(new MyWebChromeClient(){
#Override
public void onProgressChanged(WebView view, int progress) {
if (progress == 100) {
//A fully loaded url will come here
String StrNewUrl = view.getUrl();
if(TextUtils.equals(StrNewUrl,strLastUrl)){
//same page was reloaded, not doing anything
}else{
String strOldUrl = null;
//save old url to variable strOldUrl before overwriting it
strOldURL = strLastUrl;
//a new page was loaded,overwrite this new url to variable
strLastUrl = StrNewUrl;
if ( strLastUrl.startsWith("intent:") ) {
Log.d("TAG", "intent triggered");
Intent intent = null;
try {
intent = Intent.parseUri(strLastUrl, Intent.URI_INTENT_SCHEME);
// The following flags launch the app outside the current app
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
try {
startActivity(intent);
} catch (ActivityNotFoundException e) {
e.printStackTrace();
}
//reload the page before invoking other activities
view.loadUrl(strOldURL);
} catch (URISyntaxException e) {
e.printStackTrace();
}
}
}
}
super.onProgressChanged(view, progress);
}
});
I'm developing an Android app which uses a webview to display a webpage. Most of my code is related to the webview. My main activity contains a webview which displays an specific web site.
I'm trying to prevent an error when my webview.db is corrupted. I know that is not a common situation but I would like to make sure that my app will not crash.
Attempting to access the webview database when it has been
corrupted will result in a crash.
I added the method setUncaughtExceptionHandler to handle the exception. I can catch the exeption but when I tried to restart my app the webview never finishes loading.
I tried the follow code to "restart" my app:
Intent i = new Intent(context, Error.class);
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
My last try was unsuccessfully then I added some code which displays an error message, removes the webview databases and closes the app.
AlertDialog alertDialog = new AlertDialog.Builder(
DiscoverMobile.this).create();
alertDialog.setTitle("Error");
alertDialog.setMessage("Application files have been deleted or corrupted. The app will close to fix this issue. You can restart the app later");
alertDialog.setButton("OK",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int which) {
webview.getContext().deleteDatabase(
"webview.db");
webview.getContext().deleteDatabase(
"webviewCache.db");
WebViewDatabase webViewDB = WebViewDatabase
.getInstance(getBaseContext());
System.exit(0);
}
});
alertDialog.show();
Could this be a good solution?
Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
view.clearCache(true);
}
Maybe you tried this, but maybe also set the WebView Cache size to something small. I'm not sure if 0 will work, so maybe 1:
webview.getSettings().setAppCacheMaxSize(1);