🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Kotlin

Kotlinは、ジェットブレインズ社のアンドリー・ブレスラフ、ドミトリー・ジェメロフが開発した、 静的型付けのオブジェクト指向プログラミング言語です。

Q&A

0回答

1819閲覧

KotlinのWebViewで安定的にリロードを繰り返したい(HTMLの取得を含む)

sunriseforever

総合スコア0

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Kotlin

Kotlinは、ジェットブレインズ社のアンドリー・ブレスラフ、ドミトリー・ジェメロフが開発した、 静的型付けのオブジェクト指向プログラミング言語です。

0グッド

0クリップ

投稿2021/08/19 11:15

前提・実現したいこと

KotlinでAndroidアプリを作成しています。
※アプリ開発に関してはごく基礎的な知識しかなく、勉強しながら進めています。
WebViewを使用して、つながりにくいチケット購入ページへのアクセスを自動リロードにより試みる動作を実装したいです。
具体的には、
0. アクセスしたいページをロード

  1. ページのHTMLを取得して、「混雑しています」というようなページかどうか判定
  2. そのページであれば(2秒程度間隔をあけて)リロード、違っていたら(=購入ページにアクセスできていたら)何もしない

という流れです。

発生している問題・エラーメッセージ

なんとか所望の動きはするのですが、20回程度リロードを繰り返していると、ほぼ確実にアプリがフリーズしてしまいます。
自分のサーバー上のテスト用ページでリロードしている限りはフリーズは起こらないので、(混雑のために)サーバーからの応答が遅い場合に問題が発生するのかなと思っています。
また、フリーズしたためにアプリを終了して再度立ち上げると、1度もページをロードできずにフリーズしがちです。

何が原因で、どうやったら安定的な動作を実現できるでしょうか?
(半永久的に自動リロードを繰り返してほしいです)

該当のソースコード

Kotlin

1class MainActivity : AppCompatActivity() { 2 override fun onCreate(savedInstanceState: Bundle?) { 3 super.onCreate(savedInstanceState) 4 val binding = ActivityWebBinding.inflate(layoutInflater) 5 setContentView(binding.root) 6 7 binding.webView.settings.javaScriptEnabled = true // JavaScriptの有効化 8 9 val urlToLoad = "https://this-is-a-reservation-page.com" // アクセスしたいURL(例) 10 var nowHtml = "" // 変数nowHtmlにページのHTMLを代入する 11 val regex = Regex("<h2>This website is busy</h2>") // 混雑時の正規表現(例) 12 13 // JavaScriptコードとAndroidコードの間にインターフェースを作成 14 class WebAppInterface { 15 @JavascriptInterface 16 fun getHtml(html: String) { 17 nowHtml = html 18 } 19 } 20 binding.webView.addJavascriptInterface(WebAppInterface(), "Android") 21 22 binding.webView.webViewClient = object : WebViewClient() { 23 // 読み込み終了時の動作 24 override fun onPageFinished(view: WebView?, url: String?) { 25 super.onPageFinished(view, url) 26 view?.loadUrl("javascript:Android.getHtml(document.documentElement.outerHTML);") 27 // HTMLが取れるのを待つ 28 while (nowHtml == "") { 29 Thread.sleep(100) 30 } 31 if (regex.containsMatchIn(nowHtml)) { // 混雑時 32 nowHtml = "" 33 Thread.sleep(2000) // 2秒間あける 34 view?.reload() 35 } else { // アクセス成功 36 nowHtml = "" 37 } 38 } 39 } 40 binding.webView.loadUrl(urlToLoad) 41 } 42}

試したこと

onPageFinished内でぐるぐる回しているのが良くないのかなと思い、一連の操作をbinding.webView.loadUrl(urlToLoad)のあとに置く、つまり

Kotlin

1binding.webView.loadUrl(urlToLoad) 2binding.webView.loadUrl("javascript:Android.getHtml(document.documentElement.outerHTML);") 3// HTMLが取れるのを待つ 4while (nowHtml == "") { 5 Thread.sleep(100) 6} 7if (regex.containsMatchIn(nowHtml)) { // 混雑時 8 nowHtml = "" 9 Thread.sleep(2000) // 2秒間あける 10 binding.webView.reload() 11} else { // アクセス成功 12 nowHtml = "" 13}

としてみましたが、これだとwhileループが永遠に回ってしまうようです。
HTMLを取得してからif文に入ること・リロードを安定して繰り返すこと、の両立に苦戦しています。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sunriseforever

2021/08/19 22:58

ご指摘ありがとうございます。 たしかにリロードを繰り返すという意味ではDoS攻撃とも捉えられかねないですが、 ・悪意あるアクセスではない ・アクセスに成功したら処理を止める(無制限にリロードを繰り返すわけでない) ・リロード間隔を2秒間設けている という3点から、攻撃にはあたらないのではないかと考えています。 とはいえ私は専門家ではなく、この考えは甘いのでしょうか...
sunriseforever

2021/08/20 00:06

貴重な情報提供、ありがとうございます。 ネット上のモラルについて改めて考えるきっかけになりました。もっと事例等を調べて、検討してみたいと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問