WebViewでWeb Workerを使用する方法 [Android]
目次
1. 作るもの
2. 初期設定
3. 画面設計
4. HTML/JSファイル
5. コーディング
1. 作るもの
WebViewでWeb Workerを使用して「シングルタスクのJavaScript」をマルチスレッドのように動作させます。今回はバックグラウンドでプログレスバーを動かします。
WebViewで正しく設定を行わないと「Failed to construct 'Worker' cannot be accessed from origin 'null'.]」というエラーが発生してWeb Workerが使用できませんのでご注意下さい。
2. 初期設定
APIレベル
今回はWebViewコントロールを扱うのでAndroidの動作可能なAPIレベルは21(Android5.0/Lollipop)にしています。
設定方法はAndroid Studioで左のTreeViewにあるGradle Scriptsのbuild.gradleの「minSdkVersionを21」にします。
3. 画面設計
WebViewとButtonを各1つ、配置します。
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <LinearLayout android:id="@+id/linearLayout" android:layout_width="0dp" android:layout_height="wrap_content" android:orientation="horizontal" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent"> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:text="HTMLを表示する" /> </LinearLayout> <WebView android:id="@+id/webView" android:layout_width="368dp" android:layout_height="447dp" android:layout_marginStart="8dp" android:layout_marginTop="8dp" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/linearLayout" /> </android.support.constraint.ConstraintLayout>
4. HTML/JSファイル
HTML/JSをリソースに追加するにはWebViewの基本操作をご覧下さい。
[index.html]
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <script> // ワーカーの生成 var my_worker = new Worker('myworker.js'); // プログレスバー var pgs; function run(){ var len = 10000; // 毎回、プログレスバーを生成する document.getElementById("pg_parent").innerHTML = '<progress id="MyProgress" style="width:180px;"></progress>'; pgs = document.getElementById("MyProgress"); pgs.max = len; pgs.value = 0; // ワーカーを実行する my_worker.postMessage({'max':len}); } // workerからのメッセージ my_worker.onmessage = function (event) { var type = event.data.type if (type == 1){ pgs.max = event.data.max; pgs.value = event.data.pos; }else{ document.getElementById("pg_parent").innerHTML = document.getElementById("pg_parent").innerHTML + '<br>完了しました。'; } } </script> </head> <body> <p></p> <div id="pg_parent"></div> <p></p> <input type="button" onclick="run();" value="実行する"> </body> </html>
[myworker.js]
onmessage = function (event) { var max = event.data.max; // 適当な重い処理 for(var i=0;i<max;i++){ postMessage({'type':1,'max':max,'pos':i}); } postMessage({'type':2}); };
5. コーディング
Workerを使用するには
setAllowFileAccessFromFileURLsをtrue
にします。
import android.content.Context; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.view.View; import android.webkit.JavascriptInterface; import android.webkit.WebChromeClient; import android.webkit.WebView; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.InputStream; public class MainActivity extends AppCompatActivity { // リソースからファイルを生成する(/data/data/パッケージ名/files/) public boolean setRawResources(Context context , int resourcesID, String fileName){ boolean result = false; // リソースの読み込み InputStream is = context.getResources().openRawResource(resourcesID); ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte [] buffer = new byte[1024]; try{ // 1024バイト毎、ファイルを読み込む while(true) { int len = is.read(buffer); if(len < 0) break; baos.write(buffer, 0, len); } }catch (Exception e){ e.printStackTrace(); return result; } // ファイルの生成 File file = new File(context.getFilesDir() + "/" + fileName); FileOutputStream fos = null; try { fos = new FileOutputStream(file); fos.write(baos.toByteArray()); result = true; } catch (Exception e) { e.printStackTrace(); } finally { if(fos != null){ try{ fos.close(); }catch (Exception e){ e.printStackTrace(); } } } return result; } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findViewById(R.id.button).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { WebView webView = findViewById(R.id.webView); // リソースからファイルを生成する(/data/data/パッケージ名/files/に作成) setRawResources(MainActivity.this, R.raw.index, "index.html"); setRawResources(MainActivity.this, R.raw.myworker, "myworker.js"); // キャッシュクリア // ※開発時のみ有効にする webView.clearCache(true); // JavaScriptを有効にする webView.getSettings().setJavaScriptEnabled(true); // WebChromeClientを設定する // ※コレを設定しないとJSのalertは表示されない webView.setWebChromeClient(new WebChromeClient()); // Web Workerを使用可能にする webView.getSettings().setAllowFileAccessFromFileURLs(true); // ファイルを読み込む webView.loadUrl("file:///" + MainActivity.this.getFilesDir() + "/index.html"); } }); } }
スポンサーリンク
関連記事
前の記事: | WebViewでJavaとJavaScript間で相互通信する [Android] |
次の記事: | WebViewの<input type="file">でカメラ、画像からデータを取得する [Android] |
公開日:2018年06月03日
記事NO:02673