Why doesn't Android's WebView load some URLs? - java

My WebView doesn't show some URLs especially if it has the leading www. part missing. http://google.com doesn't load but http://www.google.com loads just fine. I don't get any exceptions or messages in the logcat so it seems rather hard to find out what's going on behind the scenes. Here's the snippet that actually displays my WebView.
WebView wbvBrowser = new WebView(this.objContext);
wbvBrowser.getSettings().setBuiltInZoomControls(true);
wbvBrowser.getSettings().setJavaScriptEnabled(true);
wbvBrowser.loadUrl("http://google.com");
Would any of you know what's causing this issue? I'm baffled.
Thanks.

Enable DOM Storage APIs
wbvBrowser.setDomStorageEnabled(true);

Make sure the app has permission to access the Internet. Add the following to AndroidManifest.xml:
<uses-permission android:name="android.permission.INTERNET" />

try this...
wbvBrowser.setWebViewClient(new Callback());
private class Callback extends WebViewClient{ //HERE IS THE MAIN CHANGE.
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
return (false);
}
}

This worked for me: Add an 's' to the http. Make it https
wbvBrowser.loadUrl("https://google.com");

Related

Why does MediaPlayer not prepare?

I'm using MediaPlayer to load an mp3 file and play it online. I am using this code:
try{
Log.i("tag1", "try");
mediaPlayer.setDataSource(activity.this, Uri.parse("link"));
mediaPlayer.prepareAsync();
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mediaPlayer) {
Log.i("tag2", "" + mediaPlayer.getDuration());
}
});
} catch(IOException e) {
e.printStackTrace();
}
Most of the times nothing is prepared, so I have the log.i results as below:
tag1 = try
tag2 is never executed
If, sometimes only, mediaPlayer is prepared, I get these logs:
tag1 = try
tag2 = 0 _ which is neither acceptable nor usable
Also, when I call mediaPlayer.setOnErrorListener, I get errors 1,-1004 or 1,-2147483648. Additionally, mediaPlayer.setOnInfoListener gives nothing; I think it's never called...
What could be the problem?
It is not unnecessary to mention that in the log folder of the server's file manager, I found this: "stagefright/1.2 (Linux; Android 4.4.4)". I think this could help to solve the problem. Also, related to this, can the problem be caused by PHP extensions? if yes, activating which extension solves this issue?
Any help is really appreciated.
You have a MEDIA_ERROR_IO. As the documentation says it's for File or network related operation errors.
In most cases the problem is in the implementation of the MediaPlayer class or maybe in android 4 as mentioned here
I would recommend you ExoPlayer, instead.
You are missing mediaPlayer.start() in your MediaPlayer.OnPreparedListener(). See attached kotlin code for an extending class with example http request
Error 1004: Source not found (f.e. wrong path or no stream at url)
Error 2147483648: Media format not supported at your device
Another mention: keeping references for audiofiles on device system needs persistable uri permission
Here's stripped down code for starting a radio stream in kotlin with OkHttp
class MyPlayer: MediaPlayer(), MediaPlayer.OnPreparedListener {
fun playStream() {
try {
val uri = Uri.parse( [URL] )
//check if url valid
val client = OkHttpClient()
val request = Request.Builder().url( [URL] ).build()
val newCall = client.newCall(request).execute()
if (newCall.code() != 200) {
//handle error for stream, stream not broadcasting
return
}
val headers = HashMap<String, String>()
headers.put("User-Agent", " [SOME AGENT] ")
setDataSource(context, uri, headers)
prepareAsync()
} catch (e: Exception) {
L.e("Url Parsing failed for ${e.message}")
setInternalState(State.Error, StreamErrorMapping.ShoutCastError)
}
}
}
override fun onPrepared(player: MediaPlayer) {
player.start() //<-- this call is missing in your code
}
By the way, like Ezaldeenn sahb already mentioned, I would also recommend using ExoPlayer, since it's way more faster than MediaPlayer! In my projects buffering went down from 2-4seconds (MediaPlayer) to 200ms (Exoplayer). Happy coding
It seems your problem is because of using http links instead of https. Add android:usesCleartextTraffic="true" to your manifest application tag like so:
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:usesCleartextTraffic="true"
android:theme="#style/AppTheme"
>
...
</application>
Also, don't forget to use internet permission.
Of course, I thank all my friends who put their most effort to answer this problem of mine, but none of them solved the main issue.
How I came to find a way to get rid of this situation:
I tried another Host for my files and it worked. So I decided to move all my data and databases to another Host.

Android Copy & Paste to any text field in any application

I am developing an app for commercial use with a background service that is getting transponder numbers (of animals) from an RFID reader via bluetooth.
After processing the received number I would like to send it to the clipboard and paste it in the focused text field of whatever application is currently in front which in my case is a browser app.
I already found a similar question from 2013 but with no accepted answer by now. All answers to the question just explained how to use ClipboardManager to copy and paste code within the developed application but that has not been meant by the problem as he clarified in a comment.
The simplest scenario that I could imagine is to just simulate a paste action on the android device. I would prefer not to need to install a third party app.
Just to add to Kirill's answer and assuming the app has Accessibility permission,
Create a class extending AccessibilityService and override onAccessibilityEvent method.
public class SampleAccessibilityService extends AccessibilityService {
#Override
public void onAccessibilityEvent(AccessibilityEvent accessibilityEvent) {
AccessibilityNodeInfo source = accessibilityEvent.getSource();
if (source != null) {
AccessibilityNodeInfo rowNode = getRootInActiveWindow();
if (rowNode != null) {
for (int i = 0; i < rowNode.getChildCount(); i++) {
AccessibilityNodeInfo accessibilityNodeInfo = rowNode.getChild(i);
if (accessibilityNodeInfo.isEditable() && accessibilityNodeInfo.isFocused()) {
accessibilityNodeInfo.performAction(AccessibilityNodeInfoCompat.ACTION_PASTE);
return;
}
}
}
}
}
#Override
public void onInterrupt() {
}
}
accessibilityNodeInfo.performAction(AccessibilityNodeInfoCompat.ACTION_PASTE) will paste the text that is copied to clipboard.
Also make sure you have right accessibility configuration.
config.xml
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
android:accessibilityFlags="flagDefault"
android:accessibilityEventTypes="typeViewClicked|typeViewFocused"
android:accessibilityFeedbackType="feedbackGeneric"
android:notificationTimeout="0"
android:canRetrieveWindowContent="true"
android:description="#string/testing" />
Here android:accessibilityEventTypes="typeViewClicked|typeViewFocused" will filter the events to view click or view focus.
You can also the events based on the packages using "android:packageNames" (so that your service won't get called often)
Finally declare the service in manifest,
<service android:name=".SampleAccessibilityService"
android:label="#string/app_name"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService"/>
</intent-filter>
<meta-data
android:name="android.accessibilityservice"
android:resource="#xml/config" />
</service>
If you want your app to interact with an app that isn't yours (the browser) you will have to give this app accessibility permissions. those are special kind of permission that allow apps to interact with something that is a bit more senstive.
there are accessibility actions, the one that you are looking for is the
AccessibilityNodeInfoCompat.ACTION_PASTE it allows you to preform a paste into a focused field.
Note that I'd recommend you to replace the browser with a inapp WebView, and inject the values with javascript this will be much more robust solution for your automation. you can find more info on how to run JS on a webview here: How to get return value from javascript in webview of android?

android admob error changing activity with asynctask

I have 2 activities (ListActivity and ContactsActivity)
Both works perfectly without Admob.
But if I have admob in ListActivity, it works perfectly but when I click a button to change to ContactsActivity (it have an AsyncTask function to get all contacts from mobile) the application exploits with this error:
If anyone can help me how to solve this problem or telling other options do.
Thanks in advance.
Loading of Ads might be throwing any un-handled exception. Try surrounding the ads-loading code in try-catch. Or paste the code in here.
Edit: If you are loading ads in the AsyncTask, remove it from there. Call the loading of ad after loading the contacts list.
Like:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
new LoadContactsList();
...
Method to load your ads;
}
I can confirm that adding the following code in my initial Activity solves the problem:
try {
Class.forName("android.os.AsyncTask");
}
catch(Throwable ignore) {}

How to add custom view in android's JellyBean Launcher

I am working on making custom launcher in android. I have referred the code of android's Jellybean launcher. now I want to make some modification in this launcher.
What I want : As we know there are default five work-space screens and I want to add custom view in any one of the workspace screen. My xml file should be inflated in any one of the screen.
I have tried many ways to do it but as the default launcher code is very complex still having no luck to finding out way for it.
There is already app named SOHO in Playstore doing exactly what I want. I have add the screenshot for referencing what i want.
Please help me if anyone of you having any idea to do it.
I've the answer for you. You can do it both in Launcher2 and Launcher3 package from (AOSP). Jellybean is using Launcher2 may be. I personally suggest you to go with Launcher3, it has buit-in way to do so.
Launcher3:
create a class that extends the com.android.launcher3.Launcher class and override the necessary methods like so:
public class MyLauncher extends Launcher {
#Override
protected boolean hasCustomContentToLeft() {
return true;
}
#Override
protected void addCustomContentToLeft() {
View customView = getLayoutInflater().inflate(R.layout.custom, null);
CustomContentCallbacks callbacks = new CustomContentCallbacks() {
#Override
public void onShow() {}
#Override
public void onScrollProgressChanged(float progress) {}
#Override
public void onHide() {}
};
addToCustomContentPage(customView, callbacks, "custom view");
}
}
Here R.layout.custom is the custom view that you wanted.
Then in the manifest file change the launcher activity class from Launcher to MyLauncher. And that's it.
Launcher2:
in Workspace.java create the following method:
public void addCustomView(View child){
CellLayout layout = (CellLayout) getChildAt(0);
layout.addView(child);
}
then in Launcher.java, find the following line:
mWorkspace = (Workspace) mDragLayer.findViewById(R.id.workspace);
then paste the following code somewhere after that line:
View child = LayoutInflater.from(this).inflate(R.layout.custom, null);
mWorkspace.addCustomView(child);
If I remember correctly you just need to implement a standard activity which displays a home launcher. In your Manifest.xml you just need to define it like this:
<activity android:name=".YourLauncher" android:label="#string/launcher_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
you can simply add view in default lanucher use code
wm = (WindowManager) getSystemService("window");
params = new LayoutParams();
params.type = LayoutParams.TYPE_PHONE;
params.format = PixelFormat.RGBA_8888;
params.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL
| LayoutParams.FLAG_NOT_FOCUSABLE;
params.x = 100;
params.y = 100;
params.height = WindowManager.LayoutParams.WRAP_CONTENT;
params.width = WindowManager.LayoutParams.WRAP_CONTENT;
params.gravity = Gravity.LEFT | Gravity.TOP;
wm.addView(view, params);
when you want to remove it
just
wm.removeView(v);
you also need permission
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
Good news, not so good news, bad news. Good new first.
It is possible to do what you want.
Now the not so good news.
You will have to write the launcher application from scratch(aka Home Screen). Yep, that involves doing all those nice and nifty things that the default launcher does(multiple pages, drag and drop, delete/add app icons, etc). Fortunately, its not as difficult as it sounds. Because the default launcher app itself is opensource. Though this code is complete, its not easy to read. A easier place to start would be the SDK
Android-SDK/samples/android-x/Home/
where x is the API level.
They have provided source code for an example home screen and it should give you a good start. With some perseverance and coffee, you should be able to modify the Launcher2 code to add a customized page of your own.
Now the Hard part.
Because a part of your goal is to keep the existing pages same and add a new page, getting this to work for all the flavors of android... HTC sense, Samsung TouchWiz, etc, etc is not a single person workload. They all have different features for the Home screen. Preserving these features and adding a new customized page is a tough task.

How to clear the (CSS) visited history of an Android WebView?

I try to reuse an existing WebView by clearing any private data the previous user left behind:
CookieManager.getInstance().removeAllCookie();
webview.clearHistory();
webview.clearFormData();
webview.clearCache(true);
clearHistory seems only to clear the back/forward list, accessible via API, but not the internal list used for coloring links inside the web content.
I even tried the following, suggested by another stackoverflow answer:
deleteDatabase("webview.db");
deleteDatabase("webviewCache.db");
I still have no luck: CSS :visited selectors still work after reloading the page.
An alternative would be to use the API level 11 private browsing feature (new constructor argument), but then I cannot benefit from visited links at all; and can no longer target older versions.
Maybe someone has a solution for this issue? Thanks for your help.
Summary of the answers I got so far:
I tried these two answers, but the first seems to clear HTML5 data storage and the latter seems to be specific to the built-in browser:
WebStorage.getInstance().deleteAllData();
Browser.clearHistory(getContentResolver());
WebChromeClient.getVisitedHistory(ValueCallback<String[]> callback) is only called after the first time I create a new WebView in a recently installed application.
I tried to remove the WebView from view hierachy and create a new one, but unfortunately the visited history seems to be stored for the whole application.
Override WebChromeClient and WebViewClient... Damn that was hidden.
I actually had to dig up a bit to find this out.
WebView webView = (WebView)findViewById(R.id.myWebView);
WebChromeClient myWebChromeClient = new WebChromeClient(){
#Override
public void getVisitedHistory(ValueCallback<String[]> callback) {
// called during webview initialization, original implementation does strictly nothing
// and defaults to the native method WebViewCore.nativeProvideVisitedHistory()
String[] myUserHistory = getVisitedUrlsFromMyOwnDatabase(userId);
callback.onReceiveValue(myUserHistory);
}
};
WebViewClient myWebViewClient = new WebViewClient(){
#Override
public void doUpdateVisitedHistory(WebView view, String url,
boolean isReload) {
// called whenever there is a new link being visited
insertIfNotExistVisitedUrlIntoMyOwnDatabaseForUser(userId);
super(view, url, isReload);
}
}
webView.setWebViewClient(myWebViewClient);
webView.setChromeClient(myWebChromeClient);
webView.getSettings().etc(whatever)...
I think I'm "almost there". Here's the part I managed: what it does so far is remove css history altogether, so we're halfway there. I can't get the browser to recognize the url format I'm providing in "myUserHistory", so in effect the only feature this code does is reset css history altogether, but it's only called once when the WebView is instanciated (or created, didn't check), so for a true multiuser experience you'd need to recreate the webview at each login.
My problem now is that I can't manage to load the urlHistory properly. My Honeycomb Xoom webview seems to ignore my data.
Ah well, I hope it works for you. For me just calling callback.onReceiveValue(new String[]{}); in getVisitedHistory() will be good enough.
EDIT:
I just put twenty more minutes into it because I'm curious. This method is what delegates to the WebChromeClient (mCallbackProxy = WebChromeClient).
protected void populateVisitedLinks() {
ValueCallback callback = new ValueCallback<String[]>() {
public void onReceiveValue(String[] value) {
sendMessage(EventHub.POPULATE_VISITED_LINKS, (Object)value);
}
};
mCallbackProxy.getVisitedHistory(callback);
}
It's protected in WebViewCore, which is a private attribute of WebView with no accessor. The sendMessage delegates to EventHub which is private, and WebViewCore is filled with private native methods, and one of these seems to be the one actually calling the populateVisitedLinks() method during the initialization.
Unless someone at Google adds a public method to WebView to trigger the repopulation, I'm afraid it's practically impossible to achieve your goal. Sorry :(
As a side note, all these native visited history handling really makes me wonder: why do hardware manufacturers care so much about which urls we visited? ;) <<< sarcasm
As an alternate solution, you could try adding your own CSS with the same base colors the default CSS has and switch the CSS by another one (with same color for both "types" of links) when you want to reset the visited links.
A:link{color: "#990000"; text-decoration: none;}
A:visited{color: "#990000"; text-decoration: none;}
A:hover{color: "#ff0000"; text-decoration: none;}
If you can obtain a Browser instance (maybe you can set a WebChromeClient to WebView) you can use its clearHistory() method.
Does WebStorage.clearAllData() have the desired effect? Unfortunately, the documentation on this class is very sparse compared to WebView and doesn't say whether it applies to WebViews.
The exact time you're calling clearHistory() may also have an effect. Clearing it and then navigating to a new page may still keep the first page in history, and you have to call the method after the new page has loaded.
Personally, if privacy is a real issue, I would create a new set of objects from scratch for this new session if possible.

Categories