Android: Using WebView outside an Activity context
Solution 1
Correct me if I am wrong but the correct answer to this question is that there is NO possible way to use a WebView in the background while the user is doing other things on the phone without interrupting the user by means of an Activity.
I have applied both Randy and Code_Yoga's suggestions: Using an activity with "Theme.NoDisplay" to launch a background service with a WebView to do some work. However even though no view is visible the switching to that activity for that second to start the services interrupts the user (ex. like pausing a running game that was being played).
Totally disastrous news for my app so I am still hoping someone will give me a way to use a WebView that does not need an Activity (or a substitute for a WebView that can accomplish the same)
Solution 2
You can display a webview from a service. Code below creates a window which your service has access to. The window isn't visible because the size is 0 by 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);
}
}
Also this will require the android.permission.SYSTEM_ALERT_WINDOW
permission.
Solution 3
You can use this to hide the Activity
<activity android:name="MyActivity"
android:label="@string/app_name"
android:theme="@android:style/Theme.NoDisplay">
Doing this will prevent the app from showing any Activity. And then you can do your stuff in the Activity.
Solution 4
the solution was like this, but with Looper.getMainLooper() :
@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
}
with help of @JonasCz : https://stackoverflow.com/a/28234761/466363
Solution 5
I used the following code to get round this problem:
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();
}
Pierre
Updated on June 08, 2021Comments
-
Pierre almost 3 years
I am trying to achieve Web Scraping through a background IntentService that periodically scrape a website without a view displaying on the users phone.
- Since I have to do call some javascript on the loaded page I cannot use any HttpGet's etc.
- I therefore have to use a WebView instance which can only run on an UI thread.
- Any attempts to start an Activity that use a WebView results in a View coming into the phones foreground (as per Android's design of Activities)
- Any attempts to use a WebView outside of an Activity context resulted in error pointing to the fact that you cannot use WebView on a non-UI thread.
- For various complexity reasons I cannot consider using libraries such as Rhino for UI-less web scraping.
Is there any way of working around this problem?