0

I'm attempting to allow a user to login via a WebView within a DialogPreference my application and this work fine, but I seem to be stuck on how to do this properly.

If I do this as next, I get an error

Error

Caused by: android.os.NetworkOnMainThreadException
 E/AndroidRuntime(732):  at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1117)

Code

@Override
protected void onBindDialogView(View v) {
    super.onBindDialogView(v);

    this.webViewOauth = (WebView) v.findViewById(R.id.web_oauth);     
    try {
        String authURL = this.backend.getRequestToken().getAuthenticationURL();
        webViewOauth.loadUrl(authURL);
    }
    catch (TwitterException e) {
        e.printStackTrace();
    }       
}

I can fix this by changing the ThreadPolicy, but as far as I can tell, there is a reason for this restriction

if (android.os.Build.VERSION.SDK_INT > 9) {
    StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
    StrictMode.setThreadPolicy(policy);
}

So, I switched this to an AsyncTask and I get a warning

Warning

java.lang.Throwable: Warning: A WebView method was called on thread 'AsyncTask #4'. All WebView methods must be called on the UI thread. Future versions of WebView may not support use on other threads.

Code

@Override
protected void onBindDialogView(View v) {
    super.onBindDialogView(v);

    MyLoginTask login = new MyLoginTask(this, v, this.backend);
    login.execute();
}

Both methods work, but is there a specific way to do this properly? The ThreadPolicy seems to be a hack and could cause it to block the UI thread, but I'n not sure if it actually will, while the AsyncTask method clearly is incorrect too based on the warning.

Is this an appropriate time to set the ThreadPolicy since it actually is running a UI element?

Kirk
  • 16,182
  • 20
  • 80
  • 112

1 Answers1

2

Yes, using the ScrictMode Policy is a hack, and a terrible one as stated here and here

You have two ways to solve this:

1- Return the authURL from the onPostExecute() method of your MyLoginTask. Simply define a setter in the object that calls the MyLoginTask, and have onPostExecute() assign the result to it.

2- Pass a reference to your webview to the MyLoginTask, and have it load the url in the onPostExecute(). Because onPostExecute() will always run in the UI thread, you will get rid of the warning.

In any case, do check out this post by the Android developers about 'Painless Threading'; you will certainly find it helpful: http://android-developers.blogspot.ca/2009/05/painless-threading.html

Community
  • 1
  • 1
verybadalloc
  • 5,768
  • 2
  • 33
  • 49
  • Worked perfectly. For others reading this, it was the `getRequestToken().getAuthenticationURL()` that was loading data on the UI thread and the `WebView` isn't the issue. – Kirk Jun 04 '13 at 02:14
  • Welcome to StackOverflow btw. – Kirk Jun 04 '13 at 02:15