Android: используйте WebView для WallpaperService - PullRequest
0 голосов
/ 19 января 2019

TL; DR:

Я делаю живые обои, используя WallpaperService, и хочу нарисовать их из WebView. Однако, когда я создаю WebView, его ширина и высота равняются 0, поэтому ничто не рисует, кроме цвета фона WebView. Существует старое исправление для этого в Как установить размер веб-просмотра в WallpaperService? , но в современном Android оно не работает. Я надеюсь узнать, как установить размер WebView, созданного с помощью WallpaperService.

ОРИГИНАЛЬНАЯ ПОЧТА:

Я делаю живые обои, используя WallpaperService, и я хочу, чтобы весь их контент просто представлял собой WebView (поскольку анимация выполняется с помощью JavaScript с использованием HTML). Ни один из примеров, которые я нашел для живых обоев, не использует WebView; вместо этого они используют Android Canvas. Я нашел этот пост StackOverflow: Как установить размер веб-просмотра в WallpaperService? , который, кажется, говорит о том, что это возможно, но когда я попробовал их код, я получаю сообщение об ошибке. Вот мой код:

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);
        }
    }
}

Когда я запускаю в эмуляторе и захожу в предварительный просмотр обоев в настройках, я получаю эту ошибку в logcat:

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

Если я закомментирую строку wm.addView(webView, params);, я больше не получаю эту ошибку (но, конечно, в предварительном просмотре обоев ничего не появляется, кроме черноты).

Любые указатели или предложения будут оценены!

ОБНОВЛЕНИЕ 1:

Хорошо, ошибка 2002 года была вызвана использованием TYPE_PHONE, тогда как на самом деле это должно быть TYPE_WALLPAPER. Теперь я получаю эту ошибку вместо:

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

При поиске этой ошибки появляются несколько сообщений, таких как Невозможно добавить окно - нулевой токен недействителен; ваша активность запущена? и Проблемы с созданием всплывающего окна в Android Activity , но я не уверен, что они охватывают этот случай. В любом случае, кажется, что существует множество теорий.

Одно из предложений - сделать addView в onCreate; Я попробовал, но это ничего не изменило.

Поскольку WallpaperService - это сервис, а не активность, есть ли у меня активность, чтобы добавить окно? Можно ли добавить окно в сервис? Если нет, могу ли я добавить активность в службу, чтобы добавить к ней окно?

ОБНОВЛЕНИЕ 2:

Вот полная ошибка:

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

Между тем, я пробую подход просто создать WebView, но не пытаюсь добавить его где-либо, а вместо этого рисую его на холсте поверхности, используя функцию рисования WebView. Кажется, это работает, за исключением того, что WebView имеет ширину 0 и высоту 0. В этом, конечно, смысл Как установить размер веб-просмотра в WallpaperService? , но он опирается на addView, из-за чего у меня возникают проблемы при работе.

Может быть, есть другой способ установить размер WebView, чем метод addView? Я пытался использовать setLayoutParams в WebView, и это, похоже, не работает, предположительно потому, что у WebView нет родителя? Есть ли способ установить его ширину и высоту, не требуя родителя? Или есть способ дать ему родителя без использования addView?

ОБНОВЛЕНИЕ 3:

Я попробовал еще несколько вещей, чтобы установить размер WebView. Я попробовал конструктор WebView, который принимает AttributeSet, используя этот 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" />

Я также попытался установить размер из веб-JavaScript, установив window.innerWidth, а также вызвав window.resizeTo. Я также попытался просто сделать некоторый веб-контент и убедиться, что переполнение было видно. Ни один из этих методов не сработал.

Я знаю, что WebView рисует на поверхности, потому что, если я изменю цвет фона, цвет поверхности изменится.

Все еще ищите способ установить размер WebView!

1 Ответ

0 голосов
/ 05 февраля 2019

Хорошо, у меня все работает, благодаря некоторой справке по Reddit .Поэтому в конечном итоге вам нужно создать WebView, но не пытаться прикрепить его к чему-либо.Затем вы должны настроить его таким образом, чтобы он отображал содержимое;это был последний недостающий кусок.Вот код для этого:

// 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);

Затем вы можете рисовать из WebView в Canvas SurfaceHolder, и все прекрасно.

Спасибо всем за помощь!

ОБНОВЛЕНИЕ 11 МАРТА 2019

Теперь все работает, поэтому я решил поделиться Гистомкод на случай, если он пригодится другим людям:

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

...