HTTPClient を使用して URL を呼び出し、コンテンツを変更してから、webview.loadDataWithBaseURL() を使用してデータを設定しようとしていますが、スレッドに問題があります。
メイン UI スレッドで HTTPGet 呼び出しを行うと、android.os.NetworkOnMainThreadException で致命的なエラーが発生します。
新しいスレッドで呼び出しを行い、そのスレッドの webView に値を設定すると、ログに次のような警告が表示されます。「すべての WebView メソッドは UI スレッドで呼び出す必要があります。WebView の将来のバージョンでは、他のスレッドで。」
別のスレッドで呼び出しを行い、それをクラス変数に設定し、メイン スレッドの webView に発行すると、loadDataWithBaseURL() は別のスレッドで呼び出したデータを取得しません。他のスレッドが呼び出しを終了する前に発生します。
問題は、コンテンツを別のスレッドで取得し、メイン スレッドの webView にロードするにはどうすればよいかということです。
public class Browser extends Activity {
public final String CLASS_TAG = "ScoutBrowser";
public WebView webView;
final Activity activity = this;
public String webContent;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.getWindow().requestFeature(Window.FEATURE_PROGRESS);
setContentView(R.layout.activity_browser);
webView = getWebView();
Log.i(CLASS_TAG, "Loaded App...");
}
private WebView getWebView() {
WebView view = (WebView) findViewById(R.id.webView);
view.setWebChromeClient(new WebChromeClient() {
public void onProgressChanged(WebView view, int progress) {
activity.setTitle("Loading...");
activity.setProgress(progress * 100);
if (progress == 100)
activity.setTitle(R.string.app_name);
}
});
view.setWebViewClient(new MyViewerClient());
view.getSettings().setJavaScriptEnabled(true);
webContent = "<html><body>initialized...</body></html>";
new Thread(new Runnable() {
public void run() {
webContent = callURL();
WebView view = (WebView) findViewById(R.id.webView);
view.loadDataWithBaseURL("http://www.somewebsite.com", webContent, "text/html", null, null);
}
}).start();
//view.loadDataWithBaseURL("http://www.somewebsite.com", webContent, "text/html", null, null);
return view;
}
public String callURL(){
String content = "<html><body>loading...</body></html>";
//Creates web clientclient
DefaultHttpClient httpclient = new DefaultHttpClient();
// Create a local instance of cookie store
CookieStore cookieStore = new BasicCookieStore();
// Create local HTTP context
HttpContext localContext = new BasicHttpContext();
// Bind custom cookie store to the local context
localContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
HttpGet httpget = new HttpGet("http://www.somewebsite.com/");
//System.out.println("executing request " + httpget.getURI());
Log.d(CLASS_TAG,"executing request " + httpget.getURI());
// Pass local context as a parameter
try {
HttpResponse response = httpclient.execute(httpget, localContext);
int code = response.getStatusLine().getStatusCode();
String reason = response.getStatusLine().getReasonPhrase();
HttpEntity entity = response.getEntity();
if (entity != null) {
InputStream instream = entity.getContent();
content = convertInputStream(instream);
//tv.setText(content);
}
Log.d(CLASS_TAG,"Response Code: "+code+" - "+reason);
} catch (ClientProtocolException e) {
Log.e(CLASS_TAG,"ProtocolException",e);
} catch (IOException e) {
Log.e(CLASS_TAG,"IOException",e);
}
Log.d(CLASS_TAG, webContent);
return content;
}
public String convertInputStream(InputStream is) throws IOException{
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line);
}
is.close();
return sb.toString();
}
}