I'm creating an app shows HTML5 video, for studying android programming, that uses Floating WebView.
It performs very choppy even on device that has upgraded WebView.
(I'm using lollipop-powered Nexus 5)
While it is attached on Activity(not floating) it performs buttery smooth.
Even if it is floating, it performs smoothly when any WebView is placed on Current Activity.
But if there's no WebViews on current activity like launcher, it performs very slow and jittery.
Here is part of code what I'm using:
WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
WebView = new WebView();
WindowManager.LayoutParams paramsRL = new WindowManager.LayoutParams(
800,
450,
WindowManager.LayoutParams.TYPE_PHONE,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
PixelFormat.TRANSLUCENT);
paramsRL.gravity = Gravity.TOP | Gravity.LEFT;
webView.setWebChromeClient(new WebChromeClient());
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
webView.loadUrl("html5_video_page_URL_here");
windowManager.addView(webView,paramsRL);
Is there any workaround to get around this problem?
EDIT
Added a video explains this behavior: http://youtu.be/BPDxzRRO1N8
while attached to an activity, it performs buttery smooth: http://youtu.be/aQcJRPCZWYs
on Kitkat, at least Samsung Galaxy's, it behaves buttery smooth: http://youtu.be/7Dw0tJ67eJw
I've also filed a bug at
https://code.google.com/p/chromium/issues/detail?id=460440
You can add
webView.setLayerType(WebView.LAYER_TYPE_HARDWARE, null);
Hope help you
I've been working on a application with a floating video player and I had the same issue. I didn't find the root cause of the problem but I got rid of this issue.
I have an activity that starts the Floating Video Player (basically a service that uses the TYPE_SYSTEM_ALERT type), when I added a notification player started by the Activity as well (similar to the one used by Spotify), the issue disappeared.
As I said I wasn't able to determine the root cause of the issue, but it seems that as long as the activity or something started by the activity is "active" (I'm using the term active loosely), the issue will no happen and the Webview will behave as expected.
Related
my application helps testers to find inconsistencies in layouts and makes it easier to work with the UI part using the grid layout overlay. but since android 12 (31 sdk) all clicks are suppressed by the system because they are "untrusted touch"
have any ideas?
P.S. in the article on medium it is suggested to use one of the approaches: Bubbles, Picture-in-Picture, Notifications, but this is not suitable for the gridlayout approach
link to untrusted touch android doc
Code example:
private fun showGrid() {
val overlayFlag = if (Build.VERSION.SDK_INT >= 26)
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
else WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY
params = WindowManager.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT,
overlayFlag,
WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE or
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT
)
windowManager = getSystemService(Context.WINDOW_SERVICE) as WindowManager
gridOverlay = GridOverlay(this, prefHelper.gridColor, prefHelper.gridSize)
gridOverlay?.alpha = prefHelper.gridAlpha
windowManager!!.addView(gridOverlay, params)
}
InputManager , maximumObscuringOpacityForTouch didn't solve the problem
other flags in the WindowManager also did not help.
what can be done according to the android documentation is using the Accessibility service, but this is not our approach as I don't want to be banned by Google because of using Accessibility service not for its intended purpose.
My app shows views above the lockscreen, until now I used the following code:
windowParams = new WindowManager.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.TYPE_SYSTEM_ALERT, 65794, -2);
windowParams.type = Utils.isSamsung(getApplicationContext()) ? WindowManager.LayoutParams.TYPE_TOAST : WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
windowManager.addView(frameLayout, windowParams);
This code doesn't seem to work anymore on Android O, instead, now the lockscreen is shown above the view, and the view only becomes visible after the user swipes away the lockscreen.
Granted, it could just be a bug since Android O is still in beta, but it's also possible that I missed one of Googles notes about "what's new in O".
It's no longer possible to draw over the lockscreen and other important UI elements (status bar, etc), Google removed this feature in Android O.
Source:
https://issuetracker.google.com/issues/36574245
I have a WebView with youtube video and 3 tabs. YouTube video is available in 1st Tab while in other 2 tabs there is a content.
Now i want to pause a video when user moves to other tabs. I have tried with
webView.onPause();
and
Class.forName("android.webkit.WebView")
.getMethod("onPause", (Class[]) null)
.invoke(webView, (Object[]) null);
but it is pausing whole WebView and my other 2 tabs are also not responding. How to stop just a video instead of whole WebView process
You can evaluate Javascript from android and stop video playing.
webView.evaluateJavascript(javascript, callBack);
or older versions.
webView.loadUrl(javascript);
check this
https://developer.android.com/reference/android/webkit/WebView.html#evaluateJavascript(java.lang.String,android.webkit.ValueCallback
What type video do you have? iframe or video tag?
On older devices (api <=21) I don't think this is actually possible, but an easy way to retrieve the given idea of a webview's inner controls are to:
Navigate to ../Android/android-sdk/tools/androiduiautomator.bat and open it up.
Make sure your device is connected via an ADB bridge (which it most likely will be)
Take a device screenshot of your screen and hover over the webkit control you want to call onPause which should bring up some information to the right hand side of your screen.
Substitute the id for
Class.ForName("yourId")
and just call a generic click event which should cause an inner effect of pausing. It could also be
Field.getDeclaredField("Id")
but I'm not positive. One of those two should procure a desired result.
You write you have A WebView and 3 tab, do you use from that WebView in All tab?
My Solution is that you use from Another WebView in other tab and if it tabs be selected some data that maybe be needed,be send to them.
In fact this don't solve your question, but i hope that can solve your problem.
I had similar issues with WebViews malfunctioning across my app. I decided to use the complementary function of onPause() (i.e. onResume()) in the same way:
Class.forName("android.webkit.WebView")
.getMethod("onResume", (Class[]) null)
.invoke(webView, (Object[]) null);
I'm working on an Android application with a floating WebView that plays Youtube videos using the Youtube's IFrame API. The floating view is implemented as a Service and it's always open while the user navigates through the different activities of the application, it also floats when the application is minimized.
The issue is have right now, is that the sound of the video lags or stutters when the view components are being rendered in the activities. This is the troubleshooting I've done:
I made two simple activities, no network work behind, just a bunch of Buttons in their layout. The sound gets cut for a second or more when you navigate to these activities or go back.
I've setup hardware accelerated property on my application and to the WebView. These are the params I use to add the WebView to the WindowManager
int flags = WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED | WindowManager.LayoutParams.FLAG_FULLSCREEN |
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_PHONE,
flags,
PixelFormat.TRANSLUCENT);
I've set the setLayerType to the WebView as LAYER_TYPE_HARDWARE. The following is the setup code for the WebView
WebSettings settings = webView.getSettings();
settings.setJavaScriptEnabled(true);
settings.setDomStorageEnabled(true);
settings.setDatabaseEnabled(true);
settings.setCacheMode(WebSettings.LOAD_NO_CACHE);
AndroidInterface javascriptInterface = new AndroidInterface(this);
webView.addJavascriptInterface(javascriptInterface, "AndroidFunction");
webView.setWebChromeClient(new WebChromeClient());
webView.setWebViewClient(new WebViewClient());
webView.getSettings().setLoadWithOverviewMode(true);
webView.getSettings().setUseWideViewPort(true);
webView.setVerticalScrollBarEnabled(false);
webView.setHorizontalScrollBarEnabled(false);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
webView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
} else {
webView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
I've also tried turning off hardware acceleration for the application, but the WebView needs it to play videos.
I've loaded a Youtube video, without using their IFrame API and I've got the same issue.
This is intestering, if I load a Vimeo video, the issue does NOT occur.
The issue occurs in a Nexus 5 (Android version 6.0.1) but it DOES NOT occur in a Samsung Galaxy S3 mini (Android version 4.2.2). This makes me think that the issue is related with Chromium, since WebView uses WebKit on all pre-4.4 devices, and do not use Chromium.
Does anybody have experienced this issue before? Any ideas will be useful!
Thanks in advance.
At the end I found out the way to resolve this issue. I declared the service in a another process ( specifying the android:process attribute in the Android Manifest file). The communication between the two services have to be done using IPC (Android Interprocess Communication) with Messenger.
Android added Presentation in API Level 17 (Android 4.2) to support displaying content on an external Display, such as as TV or monitor connected via HDMI, MHL, Miracast, or SlimPort. However, Presentation extends Dialog, and so it is only usable from an Activity.
And, as far as I knew, that was the end of the story.
However, this StackOverflow answer hints at a possible way to use an external Display from a Service, by means of createDisplayContext() and WindowManager created from that Context. Then, the addView() method on that WindowManager should render the View onto the indicated Display. If this can be made to work, it really opens the door for interesting uses of external displays, such as playing a video on a TV while being able to use unrelated apps (e.g., a Web browser) on the device's own touchscreen.
However, that answer glosses over a key detail: how to set up the WindowManager.LayoutParams for the addView() call. In particular, there are a dizzying array of possible TYPE_ values for the type field. I have crashed in two attempts, though with different messages:
TYPE_APPLICATION results in android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application
TYPE_APPLICATION_MEDIA results in android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running?
For example, here is my WindowManager.LayoutParams for the second scenario above:
WindowManager.LayoutParams p=
new WindowManager.LayoutParams(
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT,
0,
0,
WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA,
0, PixelFormat.OPAQUE);
Reading through the docs for type suggest that none of the TYPE_APPLICATION will be correct, as I do not have a token. Moreover, the point behind this exercise is to not have a token, as least as far as I can tell, as the Service is supposed to run independently from any UI.
If you look at the source to Presentation, it defers the WindowManager work to Dialog, which uses com.android.internal.policy.PolicyManager, which quickly dead-ends in an IPolicy. An SDK app does not have access to PolicyManager, anyway.
Has anyone gotten the createDisplayContext() approach to work from a Service? If so, what did you use for the type (or, more generally, for the WindowManager.LayoutParams in general)? Bonus points for a solution that does not involve some icky permission. :-)
Thanks!
TYPE_SYSTEM_ALERT type used conjunctly with the SYSTEM_ALERT_WINDOW permission should work.
It makes sense that launching a dialog from a service
requires "icky" permissions, it basically allows you to draw over other apps :)