Подтвердить что ты не робот

Android: использование WebView вне контекста активности

Я пытаюсь добиться веб-скрепок с помощью фона IntentService, который периодически очищает веб-сайт без отображения вида на телефоне пользователя.

  • Поскольку мне нужно сделать вызов javascript на загруженной странице, я не могу использовать HttpGet и т.д.
  • Поэтому я должен использовать экземпляр WebView, который может работать только в потоке пользовательского интерфейса.
  • Любые попытки запустить Activity, использующие WebView, приводят к представлению "Просмотр" на переднем плане телефонов (в соответствии с Android-проектами "Действия" ).
  • Любые попытки использовать WebView вне контекста Activity приводили к ошибке, указывающей на то, что вы не можете использовать WebView для потока, отличного от UI.
  • По разным причинам сложности я не могу рассмотреть использование таких библиотек, как Rhino для веб-скрепок без интерфейса.

Есть ли способ решить эту проблему?

4b9b3361

Ответ 1

Исправьте меня, если я ошибаюсь, но правильный ответ на этот вопрос заключается в том, что нет возможности использовать WebView в фоновом режиме, когда пользователь делает другие вещи на телефоне, не прерывая пользователя посредством Activity.

Я применил предложения Randy и Code_Yoga: использование активности с Theme.NoDisplay для запуска фоновой службы с помощью WebView для выполнения некоторой работы. Однако, несмотря на то, что вид не виден, переключение на это действие для этой секунды для запуска служб прерывает пользователя (например, приостанавливает выполняемую игру, которая воспроизводится).

Полностью катастрофические новости для моего приложения, поэтому я все еще надеюсь, что кто-то даст мне способ использовать WebView, который не нуждается в Activity (или замене для WebView, который может сделать то же самое)

Ответ 2

Вы можете отобразить веб-представление из службы. Приведенный ниже код создает окно, к которому имеет доступ ваш сервис. Окно не отображается, поскольку размер равен 0 на 0.

public class ServiceWithWebView extends Service {

    @Override
    public void onCreate() {
        super.onCreate();

        WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
        params = new WindowManager.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY, WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE, PixelFormat.TRANSLUCENT);
        params.gravity = Gravity.TOP | Gravity.LEFT;
        params.x = 0;
        params.y = 0;
        params.width = 0;
        params.height = 0;

        LinearLayout view = new LinearLayout(this);
        view.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT));

        WebView wv = new WebView(this);
        wv.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT));
        view.addView(wv);
        wv.loadUrl("http://google.com");

        windowManager.addView(view, params);
    }
}

Также для этого потребуется разрешение android.permission.SYSTEM_ALERT_WINDOW.

Ответ 3

Вы можете использовать это, чтобы скрыть действие

         <activity android:name="MyActivity"
          android:label="@string/app_name"
          android:theme="@android:style/Theme.NoDisplay">

Это предотвратит показ приложения. И затем вы можете делать свои вещи в Activity.

Ответ 4

решение было таким, но с Looper.getMainLooper():

https://github.com/JonasCz/save-for-offline/blob/master/app/src/main/java/jonas/tool/saveForOffline/ScreenshotService.java

@Override
public void onCreate() {
    super.onCreate();
    //HandlerThread thread = new HandlerThread("ScreenshotService", Process.THREAD_PRIORITY_BACKGROUND);
    //thread.start();
    //mServiceHandler = new ServiceHandler(thread.getLooper()); // not working
    mServiceHandler = new ServiceHandler(Looper.getMainLooper()); // working
}

с помощью @JonasCz: fooobar.com/questions/250670/...

Ответ 5

WebView не может существовать вне Activity или Fragment из-за того, что он является пользовательским интерфейсом. Однако это означает, что для создания WebView требуется только действие, а не обработка всех его запросов.

Если вы создаете невидимый WebView в своем основном действии и получаете его из статического контекста, вы должны иметь возможность выполнять задачи в представлении в фоновом режиме из любого места, так как я считаю, что все WebView IO выполняются асинхронно.

Чтобы отменить этот глобальный доступ, вы всегда можете запустить службу со ссылкой на WebView для выполнения необходимой вам работы.

Ответ 6

Я использовал следующий код, чтобы обойти эту проблему:

Handler handler = new Handler(Looper.getMainLooper());
try
{
    handler.post(
        new Runnable()
        {
            @Override
            public void run()
            {
                ProcessRequest(); // Where this method runs the code you're needing
            }
        }
    );
} catch (Exception e)
{
    e.printStackTrace();
}

Ответ 7

или заменить WebView, который может выполнить то же самое < ===, если вы не хотите показывать загруженную информацию в пользовательском интерфейсе, возможно, вы можете попытаться использовать HTTP для прямого вызова URL-адреса и обработать на возвращаемом ответ от HTTP

Ответ 8

Я знаю, что прошло полтора года, но теперь я столкнулся с той же проблемой. Я решил это в конечном итоге, запустив свой код Javascript внутри движка Node, который работает в моем приложении для Android. Он называется JXCore. Вы можете взглянуть. Кроме того, посмотрите на sample, который запускает Javascript без WebView. Я действительно хотел бы знать, что вы в конечном итоге используете?

Ответ 9

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

И затем вы просто проводите опрос результатов из RESTful Webservice или даже используете промежуточное программное обеспечение для обмена сообщениями (например, ZeroMQ).

Может быть, более элегантный, если он подходит вашему прецеденту: пусть служба очистки будет отправлять ваши сообщения Push Push через GCM:)

Ответ 10

Я не уверен, является ли это серебряной пулей к данной проблеме. Согласно принятому ответу @Pierre (звучит правильно для меня)

НЕТ никакого возможного способа использовать WebView в фоновом режиме, пока пользователь выполняет другие действия на телефоне, не прерывая его с помощью действия.

Таким образом, я считаю, что должны быть некоторые архитектурные изменения/изменения потока, которые должны быть сделаны, чтобы решить эту проблему.

Предлагаемое решение № 1: вместо того, чтобы получать push-уведомление от сервера и запускать фоновое задание, а затем запускать некоторый код JS или WebView. Вместо этого, всякий раз, когда пользователь запускает приложение, он должен запросить внутренний сервер, чтобы узнать, есть ли необходимость выполнять какие-либо проверки или нет. А на основе бэкэнда ввода Android-клиент может запустить код JS или WebView и передать результат обратно на сервер.

Я не пробовал это решение. Но надеюсь, что это возможно.