Android⇔Ionic(WebView)の文字列の受け渡し

Ionicで作成したサイトをAndroidアプリのWebView上で表示した場合、相互に値の受け渡しができるのか検証した結果を書いておきます。(通常のJavascriptだと結構ネタがあったのですがIonicとなるとあまりなかったので)

1. Android⇒Ionicへの値の受け渡し

Androidアプリのソース
```
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        //webViewというIDでWebViewを定義している
        val webView: WebView = findViewById(R.id.webView)
        webView.setWebViewClient(WebViewClient())
        webView.setWebChromeClient(WebChromeClient())
        webView.getSettings().javaScriptEnabled = true
        webView.getSettings().allowFileAccess = true;
        webView.getSettings().allowContentAccess = true;

        webView.loadUrl("https://XXXXXX.com/");
    }
    
    /**
     * ボタンクリックで"test"をIonicへ送る
     */
    fun onClickTest(p0: View?) {
        //AndroidからWebViewのJavascript関数を呼び出す
        val webView: WebView = findViewById(R.id.webView)
        webView.evaluateJavascript("recvText('test')", null)
    }
}
```

Ionicアプリのソース
index.html
```
<head>
  <script type="text/javascript">
    /* Androidから呼び出されるJavascript関数 */
    function recvText(response) {
      /* Serviceの関数を呼び出してIONICへ処理を移動する */
      window.NativeService.recvText(response);
    }
</head>
```

native.service.ts
```
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs';

//index.htmlから関数を呼び出すため定義
declare const window: any;

@Injectable({
  providedIn: 'root'
})
export class NativeService {
  private sharedDataSource = new Subject<string>();
  public sharedDataSource$ = this.sharedDataSource.asObservable();

  constructor() {
    window.NativeService = this;
  }

  /**
   * index.htmlのJavascriptから呼び出される関数
   * @param response 
   */
  public recvText(response: string) {
    //ServiceからPageへ値を渡す
    this.sharedDataSource.next(response);
  }
}
```

home.page.ts
```
export class HomePage implements OnInit, OnDestroy {
  recvText: string = "";

  private subscription!: Subscription;

  constructor(private nativeService: NativeService, private zone: NgZone) { }

  ngOnInit(): void {
    //Serviceからイベントを受信して値を受け取る
    this.subscription = this.nativeService.sharedDataSource$.subscribe(msg => {
      this.zone.run(() => {
        this.recvText = msg;
      });
    });
  }

  ngOnDestroy(): void {
    this.subscription.unsubscribe();
  }
}

```

2. Ionic⇒Androidへの値の受け渡し 

Ionicのソース
```
//Androidへ値を送信するために定義
declare global {
  interface Window {
    android: any;
  }
}

@Component({
  selector: 'app-home',
  templateUrl: 'home.page.html',
  styleUrls: ['home.page.scss'],
  standalone: false,
})
export class HomePage {

  constructor() { }

  /**
   * ボタンクリックで文字列をAnrdoidへ送る
   */
  onClickSend(): void {
    //Androidへ値を送信する
    let result = window.android.recvText("test");
  }
}
```

Androidのソース
```
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        //webViewというIDでWebViewを定義している
        val webView: WebView = findViewById(R.id.webView)
        webView.setWebViewClient(WebViewClient())
        webView.setWebChromeClient(WebChromeClient())
        webView.getSettings().javaScriptEnabled = true
        webView.getSettings().allowFileAccess = true;
        webView.getSettings().allowContentAccess = true;

        webView.addJavascriptInterface(this, "android");

        webView.loadUrl("https://XXXXXX.com/");
    }
    
    /**
     * WebViewから呼ばれる関数の定義
     */
    @JavascriptInterface
    fun recvText(message: String): String {
        //このmessageがIonicから送信された文字列
        System.console().printf(message);
        return message;
    }
}
```