Is Accessibility enabled for Android WebView? Can anyone tell how to make a WebView accessible?
The Android webview accessibility is enabled via javascript injection in Honeycomb and above (as pointed out by alanv). The user must enable it by:
Turning on Accessibility mode, including 'Explore by Touch' in 4.0+.
Enabling 'Enhanced Web Accessibility', or, on older devices, 'Inject Web Scripts'.
This works by injecting javascript into each loaded pages via <script> tags. Note that you will have to be careful, as not all content will play nice with this javascript, and the injection will fail in some edge cases.
You can extend the WebView class to implement Accessibility API methods.
http://developer.android.com/guide/topics/ui/accessibility/apps.html#custom-views
I also ran into this issue on 4.0 devices. I ended up placing a TextView on top of the WebView, making the TextView background and text transparent. The text content of the TextView being set to the content of WebView with all HTML tags stripped out.
A most inelegant solution, I know, but hey it works....
No, the WebView is not accessible from the built-in TalkBack service, at least as of Android version 4.0. Instead, blind users are instructed to use something like Mobile Accessibility for Android, which provides a spoken browsing interface. I would suggest making your content available to other processes, allowing blind users to view the content in their browser of choice. I did this by starting an intent to view the content:
public static void loadUrlInBrowser(Context c, Uri uri) {
Intent i = new Intent(Intent.ACTION_VIEW);
i.setDataAndType(uri, "text/html");
c.startActivity(i);
}
Alternatively, you can set the content description of the WebView. Note that this only seems to work in pre 4.0 versions of android. I've found that 4.0 devices keep either say WebView or nothing at all.
I know how to access web view content by Accessibility API, when AccessibilityNodeInfo.getText() is null or "null", call AccessibilityNodeInfo.getContentDescription().
simple code:
private String getTextOrDescription(AccessibilityNodeInfo info) {
String text = String.valueOf(info.getText());
if (isEmptyOrNullString(text)) {
text = String.valueOf(info.getContentDescription());
}
return text;
}
private boolean isEmptyOrNullString(String text) {
if (TextUtils.isEmpty(text) || text.equalsIgnoreCase("null")) {
return true;
}
return false;
}
getContentDescription() can get the web view content.
sorry for my poor english.
Related
I have a web page that is often launched from inside an Android/iOS app in their respective "tab system", Chrome Custom Tabs / SFSafariViewController.
The requirement I have is to have some urls redirect and open in the full browser app instead of navigating in the tab/controller.
I tried adding to one of those URLs the href target="_blank" or use window.open()` but in Android at least that opens a custom tab inside of the existing tab. Haven't had the chance to test that on iOS as of yet but I have the sneaking suspicion it will do nothing as the Safari View Controller does not support windows.
Any ideas on how I can force these 2 tools to open a url in the full apps would be much appreciated.
Thanks.
For people who might come across this and are interested.
Unfortunately it is not possible to force the in app browser to open a new tab in the full version of it. Like I mention in he question iOS simply can't do that due to the nature of the SFSafariViewController, while in Android it does not work... for reasons I guess, could not find something concrete and I will not go into speculating the reasons.
The solution I ended up using on my side is:
Have the site send a deep link to the app with the URL that should it should open externally, the app then closes the in app browser and launches the receive URL to the full browser.
I am setting this as the answer for now. If anyone comes with a better solution or an immediate solution to the problem, I am more than happy to change it.
Cheers
Twitter and whatsapp open webpages in CCT and SVC, but FB messenger doesn't, because it opens in its in-app-browser (IAB), unless you change your phone settings.
But. I found this javascript which works for me, for safari on iphone and chrome on android. Put it in the beginning of your index page at the end of your header and refer to this same index page.
Of course change yourwebpagetoopenoutsidewbhere to your own page.
var standalone = window.navigator.standalone,
userAgent = window.navigator.userAgent.toLowerCase(),
safari = /safari/.test(userAgent),
ios = /iphone|ipod|ipad/.test(userAgent);
var qq;
if (ios) {
if (!standalone && safari) {
// Safari
} else if (!standalone && !safari) {
// iOS webview
s=location.toString().split('?');s=s[1];
qq="https://www.yourwebpagetoopenoutsidewbhere.com/index.php?" + s;
window.close(); // Close the empty view window
window.open(qq,'_system', 'location=yes', replace);
}
} else {
if (userAgent.includes('wv')) {
// Android webview
s=location.toString().split('?');s=s[1];
qq="https://www.yourwebpagetoopenoutsidewbhere.com/index.php?" + s;
window.close(); // Close the empty view window
var winloc = 'intent:' + qq + '#Intent;end';
window.location = winloc;
} else {
// Chrome
}
}
I want to make an app that allows users to log-in multiple accounts of same site using different webview.
For example, I have 2 WebView.
Each WebView will load the same site such as gmail.com.
And user can log-in using separate account in separate WebView.
But the problem I am facing is that the 2 WebView always log-in to same account.
I've googled a lot, and here are some related titles,
Facebook MultiLogin in Android Webview
Using WebView for multi-page login to website and fetch data
Multiple Log-Ins on Separate WebViews? (Android)
but still no acceptable answer is found.
Would it be possible in Android using WebView?
How can I achieve what I want?
The tricky part is android.webkit.CookieManager, used by WebView to keep cookies, is designed to be a singleton. This means there'll be only one CookieManager instance per Java/Dalvik process, and your multi WebView instances inside the same process share a same set of cookies.
Like #ToYonos proposed, you may try overriding certain hooks to work around this, but I don't think it will 100% work...Also think about android.webkit.WebStorage: it's another singleton!
That said, this might work a bit more reliably: duplicate your top level WebView activity in manifest and assign them to run in different processes:
<activity
android:name=".WebViewActivity" />
<activity
android:name=".WebView1Activity"
android:process=":web1" />
<activity
android:name=".WebView2Activity"
android:process=":web2" />
...
So that you'll have isolated processes and different CookieManager/WebStorage instances.
But be warned: different WebStorage instances still writes to same path(s) in your app data folder! This may be worked around by calling webView.getSettings().setDatabasePath() to use different db paths for different processes, but this API has been deprecated in API level 19 (KitKat). Well as long as the web page you're visiting doesn't use HTML5 local storage this should be fine...
I think that you'll have to implement your own system. You could try something like that :
private static final String DOMAIN = "http://cookiedomain.com";
private final Map<WebView, String> cookiesMap = new HashMap<WebView, String>();
// [...]
WebView w = new WebView(this);
// Loading url and stuff
w.setWebViewClient(new WebViewClient()
{
public void onLoadResource (WebView view, String url)
{
// If cookies have already been stored for this WebView
if (cookiesMap.get(view) != null)
{
CookieManager.getInstance().removeAllCookie();
CookieManager.getInstance().setCookie(DOMAIN, cookiesMap.get(view));
}
}
public void onPageFinished(WebView view, String url)
{
// Check if the url matches the after-login page or whatever you want
boolean condition = ...;
if(condition)
{
// Getting new cookies
String cookies = CookieManager.getInstance().getCookie(DOMAIN);
cookiesMap.put(view, cookies);
}
}
});
// Do the same for the 2nd WebView
This is a simple example, to be improved, but it could be a good start for a sustainable solution.
Limits :
It will only work if each WebView does not make request at the same time as others. Otherwise, it will surely tangle cookies.
This will work for one domain only
I need to make an app that will only display a public web url that mainly contains HTML, I want to be able to include back and forward buttons if a exact specific url is displayed or users can swipe from the side or something to display them (NO swiping from the side or bottom). I should be able to specify which domains and subdomains should be shown in the app and everything else would be opened in safari.
I would really appreciate if someone could find some kind of (free) solution or if they would like, they could make something for anyone else who is interested in having an Web Based App Template like this. Bonus points for Android and iOS versions and even more for iOS and iPad versions. Greatly Appreciated!
This would be quite easy using UIWebView (on iOS)...
define your webview inside let's say the main UIViewController
UIWebView *webView = [UIWebView alloc]init];
webView.delegate = self
[webView loadHTMLString:#"yoursite.com" baseURL:nil]
on the delegate you should implement
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
if(request.url.absoluteString isEqualToString:#"any of the strings you want") {
return YES;
}
else {
[[UIApplication sharedApplication] openURL:request.url]
return NO;
}
}
code is actually not tested but something by this idea should work on iOS...
i only can help you with the iOS part though... hope this helps you...
PS: to use the back and forward you should create a UIToolBar with two buttons and enable and disable them using
if(webView.canGoBack)
backButton.enabled=YES;
if(webView.canGoForwad)
forwardButton.enabled=YES;
and this buttons calls the method goBack and goForward of the UIWebView..
I have an android application that loads a webview from a server. I do not have the server code so I cannot change anything in Javascript. I want to figure out when a button is being clicked in a webview and what is the label in the button. I do not know the Id, I just want to get the label.
I tried searching for this but could not find an answer. I found solutions where you can work in the javascript but in my case I cannot.
This suggestion may help to find useful information that could lead to determination of your button label. Override shouldOverrideUrlLoading(), shouldInterceptRequest() and/or onLoadResource() for the WebViewClient so you can get at the URL of any redirects.
Example:
webview.setWebViewClient(new WebViewClient() {
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// Try to learn something useful from the 'url' here.
// Continue as normal, loading the 'url' within this WebView.
view.loadUrl(url);
return false; // Allow the WebView to handle the request.
}
// Optional: Add similar for "shouldInterceptRequest()" and/or "onLoadResource()".
});
Note: Overriding shouldOverrideUrlLoading() as above is the standard way to keep redirects within the same WebView rather than redirecting to the default browser application.
You might really want to check this page:
Building Web Apps in WebView (Google API Guides)
Specifically, it seems that addJavascriptInterface might be what you are looking for:
addJavascriptInterface(Object object, String name)
It allows you to execute your Java code from javascript and, paired with the ability to insert code in a page, it's an incredibly powerful tool for granting you a high level of coupling between your Activity and your page.
I think that at this point you will already know what to do, but I'll sketch a possible course of action anyway:
create a javascript interface with the callbacks you want executed in your activity when a button is pressed
as soon as your page loads, install the code to call your javascript interface in each button (or link) by injection
Hope this helps
The webview with google search result links loaded in my android app, when I clicked on the links, it is opening up a blank screen.
I think, it is something to do with onmousedown event attached with every href links in the result page.
will be very thankful if I am provided with a way to handle this and make webview to actually openup the link that I am clicking on.
Here's another solution. After Google finishes loading the blank page you load the WebView with the previous page (which is the actual result) using the WebView's tag or a member variable. Like this:
#Override
public void onPageFinished(WebView view, String url)
{
System.out.println("onPageFinished: " + url);
if ("about:blank".equals(url) && view.getTag() != null)
{
view.loadUrl(view.getTag().toString());
}
else
{
view.setTag(url);
}
}
Here's my LogCat:
I/System.out(13182): onPageFinished: http://www.google.com/#hl=en&sugexp=les%3B&gs_rn=1&gs_ri=tablet-gws&cp=2&gs_id=9&xhr=t&q=amazon...
I/System.out(13182): onPageFinished: http://www.amazon.com/
I/System.out(13182): onPageFinished: about:blank
I/System.out(13182): onPageFinished: http://www.amazon.com/
I'm having the same problem. I get the "about:blank" page when I click on Google search results in a WebView in my Asus Transformer TF700 running 4.1.1. It doesn't happen in my Acer A100 tablet or other phones.
I noticed the result links work when I switch from Tablet to Classic version at the bottom of main Google Search Page.
https://www.google.com/?nota=1
If you remove the ?nota=1 in the above URL you won't see the Tablet option in your PC. In your tablet however the default google.com URL displays the Tablet option at the bottom.
If you use nota=1 in your search results page the links will work. Like this:
http://www.google.com/search?nota=1&q=amazon
I know this is not perfect. We'd like the default Google search results page's links to work. Google is doing something funky on the Tablet version which Asus Transformer doesn't seem to like!
I will post an update when I figure out what is causing this. Oh! the fun with Android :)
I wanted to add this as a comment to Stan Texan's answer, but I don't have enough rep points...
I'm testing on an older tablet (LG Optimus Tab/DoCoMo L-06c/T-Mobile G-Slate/Rogers LG V909) running Honeycomb (3.1) and my WebView is running into the same problem on Google's website.
Google's own browser works just fine when navigating to www.google.com, but when I use that url in a WebView in my app, the links are all "about:blank". 0_o
Therefore, if the user wants to go to Google's search page, I rewrite the url as follows:
//get the url from the user..
inUrl = urlAddressEditText.getText().toString();
// make sure it's properly formatted...
...
// then add the "/?nota=1&" if it's a Google domain.
String outUrl = inUrl.replaceFirst("(www\\.google\\..*/?)(\\??)", "$1/?nota=1&");
webView.loadView(outUrl);
So far this works, but I haven't tested it out for every scenario.
I had a look at your Vuwize app. Instead of embedding www.google.com directly into a WebView, you seem to have your own search form, run a Google search, and then render the result page yourself. This could explain your problem because result links in search results from Google is not straight href links to original pages. To understand more about your problem, it's necessary to see what exactly you're doing and how you run Google search from your server side.
If you just embed www.google.com in a WebView directly like this:
setContentView(R.layout.main);
mWebView = (WebView) findViewById(R.id.webview);
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.loadUrl("http://www.google.com");
mWebView.setWebViewClient(new HelloWebViewClient());
Users can enter search directly into Google and get result pages, where links are all clickable in the same WebView.
Here's another solution to handle blank pages caused in Jelly Bean. I found 2 URLs that cause blank pages. Override loadUrl(String) and not load them at all.
#Override
public void loadUrl(String url)
{
if (url != null && !(url.startsWith("file:///android_asset") || "about:blank".equals(url)))
{
super.loadUrl(url);
}
}