KotlinでHelloWorldとWebViewを使ってみた


目次

これまでただ単に入れていただけのAndroid Studioを触ってみることにした。まずは弊サイトを表示するアプリを作ってみようかと思い、Webviewで表示することを目指すことにする。

Homebrewで整える。

以前にインストールだけしていたので、まずはアップデート

1
2
3
4
5
6
7
$brew cask upgrade android-studio

==> Upgrading 1 outdated package:
android-studio 3.1.4.0,173.4907809 -> 3.5.2.0,191.5977832
==> Upgrading android-studio
==> Downloading https://dl.google.com/dl/android/studio/install/3.5.2.0/android-studio-ide-191.5977832-mac.dmg
######################################################################## 100.0%

完了。3.1.4から3.5.2にアップデートされた。

の通りに、android-studioを起動して[File] > [New] > [New Project]を選択。[Choose your project] ウィンドウで [Empty Activity] を選択し、[Next] 
[Configure your project] ウィンドウの中身がリファレンスと若干違った。
Minimum API level でAndroidOSのシェア率がわかるっぽい。デフォルトで選択されている4.0.3であれば100%全てのデバイスが利用できるみたいだが、4.1.0になると99.6%となった。

Nextを押したところ、足りないコンポーネントのインストールが始まった。

Empty Activityで最初にできるのは、Hellow Worldの状態のようなので、さっそくここから起動をしてみることにする。
手元にあるAndroidデバイスはお遊び用のatom(2.5インチ?)のためhellow worldを表示するためとしても厳しいのでエミュレータを用いることにする。
ToolからAVD Managerを見つけることができなかったので、アイコンから起動することにした。
エミュレートするOSバージョンを決めてダウンロードする。弊回線は貧弱なのでここで時間がかかった。
ライセンスアグリーメント(アグリーしないと進めれない)。こういうのはほぼ強制なんだし、「以後全てに同意するので2度と出さない」オプションが欲しい。AcceptしてNextを押すとコンポーネントのダウンロードが始まる。ここもめっちゃ重い。時間かかる。
プロジェクト画面が開いた後、自動でBuildが走るが、この時に一度フリーズして落ちた。再度復帰させたが、リビルドの方法がわからず、自動Buildが終了してないために、ビルド設定を自分でセットアップする必要ができてしまったので、再度プロジェクトを開始した。

立ち上げ直すてデバッグしようとしたら、設定がないから自分で設定しなさいとのこと。なるほどわからん。

再度最初からやり直したら今度はフリーズしないでBuildできた。

webviewの設定

当初の目標通り、自サイトをWebViewで動かすアプリを作ってみることにする。activity_main.xmlにWebViewを載せる。パーツの乗せ方がわからん。ぐぐってもいまいちヒットしない(小一時間)
かなり悩んでからようやくココが選択できるパーツなのだと気がついた。まったくもって視野に入ってなかった。画面の中央にあったというのに(笑

webviewを実行するアプリを起動することはできるようになったため、このサイトを表示するだけの単純なアプリをデバッグしてみることにする。

起動すると、”net::ERR_CHACHE_MISS” というエラーが表示されてサイトに接続されない。エミュレータからHost端末の回線を拾えていないのかと思い(だとしてもCHACHE_MISSは変だが)エミュレータ上でChromeを起動してインターネット接続ができるかを確かめる。

できる。

となると、アプリからインターネット接続ができていないということなので、その点に絞って確認した。

小一時間ほどググってようやく、AndroidManifest.xmlに

 

1
<uses-permission android:name="android.permission.INTERNET" />

と記載しないと、文字通りインターネット接続ができないことを知った。一つ賢くなった。

上記の設定を入れた後に、再度デバッグしてみると、エラーメッセージが変わった。

一歩前進した!と喜ぶも今度はこっちの改善手法が全くわからない。再度悩む。

結論としては、

default prettyprint prettyprinted

Just started to develop android apps and got the same error even when I had permission:

<uses-permission android:name=“android.permission.INTERNET”/>

Then I’ve uninstalled the app inside emulator and build again and now the app can access internet.

参考:https://stackoverflow.com/questions/57131662/err-access-denied-in-webview-in-android

というコメント。「まさかぁ」と思いながら、エミュレータからアンインストールして再度ビルドしなおしたら接続できた。マジでか。

webviewを利用するので、デバッグも入れておきたかった。こちらはリファレンスを読んだらすぐにわかった。

1
WebView.setWebContentsDebugginEnabled(true)

を設定した上で、google chromeを開いて、 chrome://inspect  にアクセスすると起動中のエミュレータ端末のwebviewの情報が取得できるようになった。

最後に勉強がてら、適当にユーザエージェントを指定しつつ、webview内でのJavascript, Cookieを許可する設定を入れるところまで確認した。

今回、Android Studioを触ったことがない状態で、IDEの使い方含め、簡単なAndroidアプリを調べつつ触ってみることには苦労した。特に、Javaでの実装例は多いがKotlinでの実装例、サンプルが少ないことに苦労した。リファレンスを読みつつ、多くのAPIとその実装方式は似通っているのでJavaでの実装例を参考に作ることができた。先人の知恵に感謝。

最終的に作ったコードは以下のようになった。

MainActivity.kt

package com.example.myfirstwebview
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.webkit.CookieManager
import android.webkit.WebView
import android.webkit.WebViewClient
class MainActivity : AppCompatActivity() {
private lateinit var webView: WebView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
webView = findViewById(R.id.webView)
webView.webViewClient = object:WebViewClient(){
override fun shouldOverrideUrlLoading(
view: WebView?,
url: String?
): Boolean {
view?.loadUrl(url)
return true
}
}
// webView上でjavascriptをONにする。
// webView.settings.javaScriptEnabled(true)ではなかった。
webView.settings.javaScriptEnabled = true
// Cookieの設定。
val cookieManager = CookieManager.getInstance()
cookieManager.setAcceptCookie(true)
cookieManager.setAcceptThirdPartyCookies(webView,true)
WebView.setWebContentsDebuggingEnabled(true)
// headerの拡張。HashMapという機能で拡張ができる模様
val extraHeaders = HashMap< String ,String>()
extraHeaders["User-Agent"] = "Mozilla/5.0 (Linux; U; Android 2.2.1; en-us; Nexus One Build/FRG83) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1"
webView.loadUrl("https://gatolynx.tokyo", extraHeaders)
}
}
view raw MainActivity.kt hosted with ❤ by GitHub

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myfirstwebview">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>