0

I retrieve some data from html after several step (login, click on link, run javascript, etc.) using webview, like described here: how to get html content from a webview? putting more actions in cascade. I don't use thread, mainly when an action (login for example) is done, it's called onPageFinished and this fire another webview.loadUrl and so on to another onPageFinished till all the actions are executed.

I want to create a widget that show this result, that fire this chain of webview.loadUrl when the widget refresh button is pressed or every day at 12AM. Only after that all the chain is completed, the result can be showed in the widget.

I've read some tutorials, and I saw that there're different approach, TimerTask, Service, Broadcast receiver, ect., but I didn't understand which fit to my project. I don't know if my explaination was clear, but in the onUpdate of the widget, I shoud start the webview.loadUrl sequence, but I can't return anything until the last onPageFinished is called.

This is what I mean for chain action, urlChain is a static string LinkedList with the sequence of URLs (and other stuff).

@SuppressLint("SetJavaScriptEnabled")
private void callChain()
{
    /* WebViewClient must be set BEFORE calling loadUrl! */
    browser.setWebViewClient(new WebViewClient() {
        @Override
        public void onPageFinished(WebView view, String url)
        {
            /* This call inject JavaScript into the page which just finished loading. */
            if (!urlChain.isEmpty())
            {
                callChain();
            }
        }

    });

    /* load a web page */
    if (!urlChain.isEmpty())
    {
        String currentUrl;
        currentUrl = urlChain.pop();
        browser.loadUrl(currentUrl);
    }
}
Community
  • 1
  • 1
Accollativo
  • 1,537
  • 4
  • 32
  • 56
  • So u want to keep all urls in some kind of linklist. So click at refresh button, want show all browsed urls or the html content of all browsed urls? – Neha Feb 13 '14 at 07:31
  • Yes, I've all urls in a LinkedList called urlChain and this linked list is consumed by the method above. When I click on refresh button on the widget, I don't want to show any web pages, I want just retrieve the data contained on the last url in my urlChain LinkedList (I've several urls because I need several step to get in the last url). – Accollativo Feb 13 '14 at 08:54
  • 1
    U need to save that urlchain string list on some storage so when app come back from pause or in-acctive state u can still get that – Neha Feb 13 '14 at 09:03
  • If u keep loading one by one urls in webview as per above approach what is the issue?? if u keep loading pages only concern is user click the page links and if you want to prevent it then hide webview and show loading screen untill linklist is empty !! – Neha Feb 13 '14 at 09:21
  • Exactly there's no user interaction, the urls are loaded one by one, and the last fire a method that handle the data harvest from last web page. The issue is maybe that I didn't understand totally how widget work. I suppose that I've to start a service when the refresh button is pressed, the service should start my callChain() method and after that I retrieve the data from the last page, I should notify and end the service, and update the widget. Right? – Accollativo Feb 13 '14 at 09:32
  • if u donot want user to interact and let them show those pages why using webview ? what purpose its solving? you can loop through linklist and show last url on widget click. – Neha Feb 13 '14 at 09:34
  • 1
    Do u want to keep hitting all urls of a linklist until its reach end and retrieve data(htmlcontent) of each page [maybe u saving or using it somewhere] then show some result base on it ..!! so meanwhile u show loading screen, its kind of long process whats u do in between at screen?? – Neha Feb 13 '14 at 09:46
  • I don't want to show any web pages, I need only data. I know that it's a long process, so when the user click on refresh button on the widget, until I retrieve htmlcontent from the last page, I was thinking to show a circle progress bar, and when the long process is done, show the useful part of htmlcontent on the widget. – Accollativo Feb 13 '14 at 10:01
  • 1
    Well if u deiced to show loading screen and hold user for that time .its not matter u do the fetching process on service or async task.. (those make sense when user can interact with UI which they do work in background). I will say keep a webview as hidden and do ur chain url process and in ui show loading screen. Honestly it will be not pretty if ur urls are in 1000. for faster u can use async task to do httpclient connection and it will give u data. – Neha Feb 13 '14 at 10:07
  • Same question like below: so my method callChain() should go inside a class that extends Service. And in [my showHTML](http://stackoverflow.com/a/8201246/1878854) (the method that I use to retrieve html data) I should put something like this link http://stackoverflow.com/a/7738687/1878854 . Is it right? – Accollativo Feb 13 '14 at 21:45

1 Answers1

0

It is probably a good idea to perform the background work on a Service or some other independent structure, fireing an update to the widget or performing an direct update on all widgets afterwards, which then causes the fresh data to get displayed.


Without knowing anything about your exact project, the cleanest way would probably be a SyncAdapter, peforming the synchronization in the background and updating a ContentProvider which can then get used when updating the widget.

However this may be overkill (you need to register a sync account in the system, etc), depending on your actual needs. You could as well just have a Service the widget may request an update on, which then fires an update using the same technique once it finished loading.

Oh, and if you're bound to exactly 12 AM, have a look at AlarmManager.

Community
  • 1
  • 1
dst
  • 3,307
  • 1
  • 20
  • 27
  • So I've to start a service when the refresh button is pressed (and when it's 12AM), the service should start my callChain() method and after that I retrieve the data from the last page, I should notify and end the service, and update the widget like in the question that you linked. Right? – Accollativo Feb 13 '14 at 10:06
  • And your service should store the result somewhere for your widget to access it. Right. What you display on the widget while the request is running is up to you, maybe add some information that it is currently fetching new data. – dst Feb 13 '14 at 20:21
  • I don't understand: is it my widget that should access to the data stored in the service? I though that was my service that when it's done with all the urls should awake the widget like you linked. Another important question, so my method callChain() should go inside a class that extends Service. And in [my showHTML](http://stackoverflow.com/a/8201246/1878854) method I should put something like your link http://stackoverflow.com/a/7738687/1878854 . Is it right? – Accollativo Feb 13 '14 at 20:59
  • in your `showHTML` (which should probably get renamed) you'd store the result somewhere the widget provider's `onUpdate` can fetch it from (`SharedPreferences`, `ContentProvider`, a file in the cache folder, ...). Forcing the widget to update from the service will trigger `onUpdate` on the widget provider. – dst Feb 13 '14 at 21:56
  • And in this case who is that start the service? Could you link me some similar examples? In the [examples](http://www.vogella.com/tutorials/AndroidWidgets/article.html) that I found, it's the onUpdate method of the widget provider that start the service (service in which I suppose the callChain() go inside, right?). So if it start the service, it can't fetch the data, because it have to wait for the end of the service and that showHTML() is called. Where am I wrong? – Accollativo Feb 14 '14 at 16:57
  • 1
    The example you linked used another way of updating, which will cause widgets to initially display no data (instead of old data when using the method I initially described). If you want to use that way, you'd call your `callChain()` inside your `Service`'s `onStart` method, right. In your `showHTML()` you'd then update the widget. The widget itself would thus not get updated until `showHTML()` is called. I'd assume that `callChain()` is not blocking, is it? Thus the `Service`'s `onStart` would end, before the callback triggers `showHTML()`(was that your question?). – dst Feb 16 '14 at 04:43
  • callChain() is not blocking, when it's ended, after few second when the web page is totally loaded, it's triggered onPageFinished event (you can find it inside of callChain) (and under some circumstances it's triggered too showHTML). Yes, my question was the last that you said. In your way of updating I've not clear when and who start the service that call callChain(). (Just a curiosity, for my purposes I think that my way of updating is better) – Accollativo Feb 16 '14 at 22:18
  • In the way I proposed you'd start the chain from the code handling the refresh button's `Intent` and in regular intervals (`SyncAdapter`, `AlarmManager`, ...). – dst Feb 17 '14 at 14:42