Android: Use WebView for WallpaperService

断了今生、忘了曾经 提交于 2019-12-02 04:25:22

问题


TL;DR:

I'm making a live wallpaper using WallpaperService, and I want to draw to it from a WebView. However, when I create the WebView, it's 0 width and height, so nothing draws but the WebView's background color. There is an old fix for that in How to set size of webview in WallpaperService? but it doesn't appear to work in modern Android. I'm hoping to learn how to set the size of the WebView created from a WallpaperService.

ORIGINAL POST:

I'm making a live wallpaper using WallpaperService, and I want all of its content to simply be a WebView (since the animation is done with JavaScript using HTML). None of the examples I've found for live wallpaper use WebView; they use the Android Canvas instead. I have found this StackOverflow post: How to set size of webview in WallpaperService? which seems to say that it's possible, but when I tried their code I end up getting an error. Here's my code:

public class MyLWPService extends WallpaperService {
    @Override
    public void onCreate() {
        super.onCreate();
    }

    @Override
    public Engine onCreateEngine() {
        return new MyEngine(this);
    }

    public class MyEngine extends Engine {
        public MyEngine(Context context) {
            WebView webView = new WebView(context);
            webView.setVisibility(webView.GONE);
            webView.loadUrl("http://example.com/");

            WindowManager wm = (WindowManager)context.getSystemService(WINDOW_SERVICE);
            WindowManager.LayoutParams params = new WindowManager.LayoutParams(
                    WindowManager.LayoutParams.WRAP_CONTENT,
                    WindowManager.LayoutParams.WRAP_CONTENT,
                    WindowManager.LayoutParams.TYPE_PHONE,
                    WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
                    PixelFormat.TRANSLUCENT
            );

            params.width = 200;
            params.height = 200;

            wm.addView(webView, params);
        }
    }
}

When I run in the emulator and go into the wallpaper preview in the settings, I get this error in logcat:

android.view.WindowManager$BadTokenException: Unable to add window android.view.ViewRootImpl$W@e1a9690 -- permission denied for window type 2002

If I comment out the wm.addView(webView, params); line, I no longer get that error (but of course nothing shows up in the wallpaper preview but blackness).

Any pointers or suggestions would be appreciated!

UPDATE 1:

Okay, the 2002 error was caused by using TYPE_PHONE, when it should in fact be TYPE_WALLPAPER. I'm now getting this error instead:

android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running?

Searching for that error brings up a few posts such as Unable to add window -- token null is not valid; is your activity running? and Problems creating a Popup Window in Android Activity but I'm not sure they cover this case. At any rate, there seems to be a lot of theories.

One suggestion is to do the addView in the onCreate; I gave that a try but it didn't make a difference.

Since the WallpaperService is a service, not an activity, do I even have an activity to add the window to? Is it possible to add a window to a service? If not, can I add an activity to the service so I can add the window to that?

UPDATE 2:

Here's the full error:

2019-01-24 14:01:21.929 1914-6592/? W/WindowManager: Attempted to add wallpaper window with unknown token null.  Aborting.
2019-01-24 14:01:21.930 32356-32356/? D/AndroidRuntime: Shutting down VM
2019-01-24 14:01:21.931 32356-32356/? E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.pixfabrik.livingworlds, PID: 32356
    android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running?
        at android.view.ViewRootImpl.setView(ViewRootImpl.java:798)
        at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:356)
        at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:93)
        at com.pixfabrik.livingworlds.MyLWPService$MyEngine.onSurfaceCreated(MyLWPService.java:130)
        at android.service.wallpaper.WallpaperService$Engine.updateSurface(WallpaperService.java:884)
        at android.service.wallpaper.WallpaperService$Engine.attach(WallpaperService.java:1020)
        at android.service.wallpaper.WallpaperService$IWallpaperEngineWrapper.executeMessage(WallpaperService.java:1343)
        at com.android.internal.os.HandlerCaller$MyHandler.handleMessage(HandlerCaller.java:37)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:193)
        at android.app.ActivityThread.main(ActivityThread.java:6669)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
2019-01-24 14:01:21.938 1914-1929/? I/ActivityManager: Showing crash dialog for package com.pixfabrik.livingworlds u0

Meanwhile, I'm trying the approach of just creating the WebView but not trying to add it anywhere, but instead drawing it to the surface's canvas using the WebView's draw function. This seems to be working except the WebView is 0 width and 0 height. That is of course the point of How to set size of webview in WallpaperService?, but it relies on addView, which is what I'm having trouble getting to work.

Might there be another way to set the WebView size than the addView technique? I've tried using WebView's setLayoutParams, and that doesn't seem to work, presumably because the WebView doesn't have a parent? Is there a way to set its width and height without requiring a parent? Or is there a way to give it a parent without using addView?

UPDATE 3:

I've tried some more things to set the WebView size. I tried the WebView constructor that takes in an AttributeSet, using this XML:

<?xml version="1.0" encoding="utf-8"?>
<WebView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="500dp"
    android:layout_height="500dp" />

I also tried setting the size from within the web JavaScript, by setting window.innerWidth, and also by calling window.resizeTo. I also tried just making some web content and making sure overflow was visible. None of these techniques worked.

I do know that the WebView is drawing to the surface, because if I change the background color, the color of the surface changes.

Still looking for a way to set the size of the WebView!


回答1:


Okay, I've got it working, thanks to some help on Reddit. So ultimately you need to create a WebView but not try to attach it to anything. Then you have to size it so it shows content; that was the last missing piece. Here's the code for that:

// Get the screen width and height and put them in screenWidth and screenWidth 
// and then do the following with them:
int widthSpec = View.MeasureSpec.makeMeasureSpec(screenWidth, View.MeasureSpec.EXACTLY);
int heightSpec = View.MeasureSpec.makeMeasureSpec(screenHeight, View.MeasureSpec.EXACTLY);
webView.measure(widthSpec, heightSpec);
webView.layout(0, 0, screenWidth, screenHeight);

Then you can draw from the WebView to the SurfaceHolder's Canvas and everything is lovely.

Thank you all for the help!

UPDATE 11 MAR 2019

It's all working now, so I thought I'd share a Gist of the code in case it's useful to other people:

https://gist.github.com/iangilman/71650d46384a2d4ae6387f2d4087cc37



来源:https://stackoverflow.com/questions/54263346/android-use-webview-for-wallpaperservice

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!