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));
Related
I HAVE ALREADY TRIED How to handle intent:// on a webView URL?
This solution just opens up a Google Play Store Web Page in my WebView, what I want is on the click, another app should open whose intent is provided as happens in Chrome.
My app has a WebView that works fine. At one stage, the WebView requests access to the following(an external payment app):
intent://pay/?pa=digitalshowroom1.payu#indus&pn=DOTPE%20PRIVATE%20LIMITED&tr=13261664955&tid=CX0FOrvSrHzDh7gP&am=1.00&cu=INR&tn=OrderId-CX0FOrvSrHzDh7gP
When I use the same website that my WebView is using in Chrome, it opens the external payment app successfully, i.e. Chrome is able to handle that intent, how can my app handle the same intent.
I seem to know I have to use
public boolean shouldOverrideUrlLoading(WebView view, String url)
for this, and I'm using it as follows:
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url != null && (url.startsWith("whatsapp://") || url.startsWith("tel") || url.startsWith("market"))) {
view.getContext().startActivity(
new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
return true;
}
else {
return false;
}
Now, this piece of code is handling the intents like opening WhatsApp, Calling app, etc. fine as they start with whatsapp or tel, so I'm able to leverage the url.startsWith() method.
How can I handle the links that request access to external apps and start with intent://?
Thanks in advance!
I tried something similar and found you have to build the URI like this and handle all URL parameters and call the build method. I did it for a UPI payments app. Call this method in shouldOverrideUrlLoading().
public void openPaymentApp(final String url)
{
try {
String pa= url.substring(url.indexOf("pa=")+3,url.indexOf("&pn"));
String pn=url.substring(url.indexOf("pn=")+3,url.indexOf("&tr"));
String tr=url.substring(url.indexOf("tr=")+3,url.indexOf("&tid"));
String tid=url.substring(url.indexOf("tid=")+4,url.indexOf("&am"));
String am=url.substring(url.indexOf("am=")+3,url.indexOf("&cu"));
String cu=url.substring(url.indexOf("cu=")+3,url.indexOf("&tn"));
String tn=url.substring(url.indexOf("tn=")+3,url.indexOf("#Intent"));
Uri uri =
new Uri.Builder()
.scheme("upi")
.authority("pay")
.appendQueryParameter("pa",pa)
.appendQueryParameter("pn",pn)
.appendQueryParameter("tr",tr)
.appendQueryParameter("tid",tid)
.appendQueryParameter("am",am)
.appendQueryParameter("cu",cu)
.appendQueryParameter("tn",tn)
.build();
Intent launchIntent = getPackageManager()
.getLaunchIntentForPackage( "com.package.name");
launchIntent.setData(uri);
startActivity( launchIntent );
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(getApplicationContext(),"Coudln't open", Toast.LENGTH_SHORT).show();
}
}
Use below code:
Uri uri = Uri.parse(url);
if (uri.getScheme().equals("intent")) {
String appPackage = getAppPackageFromUri(uri);
if (appPackage != null) {
PackageManager manager = getContext().getPackageManager();
Intent appIntent = manager.getLaunchIntentForPackage(appPackage);
if (appIntent != null) {
getActivity().startActivity(appIntent);
} else {
// open external website
}
}
}
Please use code if any issue let me know
Happy coding!
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.
if there is no internet means I'm not able to load web resources. For this reason I'm giving the toast like "Check internet connectivity". After this toast, user may enable the internet option at notification bar and comes back. When he comes back, i want to reload the activity. For this requirement, i tried
onWindowFocusChanged and onActivityReenter
override methods but these are not working properly
MyCode
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if(hasFocus){
Intent intent = new Intent(CommonActivity.this, OtherActivity.class);
startActivity(intent);
}
}
When I'm using above code, my activity reloading again and again
There is a solution which i know is not perfect but it will work.
Define a activity level veriable like this
Boolean isAlreadyFocused = false;
Then in your onFocusChanged method do like this.
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if(hasFocus && !isAlreadyFocused ){
isAlreadyFocused = true;
Intent intent = new Intent(CommonActivity.this,OtherActivity.class);
startActivity(intent);
}else{
isAlreadyFocused = false;
}
}
Check this and tell me if this does not work.
By fallowing another way (i got this idea when i saw the flipkart app) i solved this internet checking
I'm checking for the internet connection, if there is no internet means i'm redirecting to NoInternetActivity that's design looks like
When user clicks on Retry button means i'm again checking for internet. If internet was accessible means i'm allowing user to home page of my app otherwise i'm redirecting to the NoInternetActivity again
I am trying to implement an app, that uses WebView to show a website which has a form inside. The problem is, when user fills the form and just before the Send button is pressed, the internet connection is lost. In this case, I receive onErrorReceived callback, and here is my implementation:
#Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
mDisconnected = true;
mDisconnectUrl = failingUrl;
mWebView = view;
mWebView.saveState(mWebViewState);
}
So I try to store the content of the form here and the failing url, so I can continue sending it when the connection established again. So I have another thread trying to make a new Socket connection with the server, and when it succeeds, I call a function in my WebViewClient class reconnect():
void reconnect(Context appContext) {
if (mDisconnected) {
try {
((Activity) appContext).runOnUiThread(new Runnable() {
public void run() {
mWebView.reload();
mWebView.restoreState(mWebViewState);
}
});
} catch (Exception e) {
mWebView.goBack();
}
mDisconnected = false;
}
}
So I try to make a reload and restore the form data so the WebView can continue with its send operation. The problem is when the page is again loaded, all the data entered in the form are lost and it does not continue with the Send operation, which was already clicked before the connection is lost. Has any one any idea, how to solve this problem.
The data is very sensitive, so it is important to continue with sending. It is also possible to let the user fill the form again and send it again, but it is not wanted in this scenario.
EDIT:
Maybe the question can be simplified. Is there any function or way to refresh a website in WebViewClient, which continues where it was left of and retrieves the form data into the state before the problem was occured.
Use database to store the contents of form and then send the data through service.
Delete the contents of database upon successfull submission.
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.