はつねの日記

Kinect, Windows 10 UWP, Windows Azure, IoT, 電子工作

ハイブリッドアプリの習作

アプリ自体はWebアプリだけれど、ネイティブアプリの中にWebViewを突っ込んでそのWebアプリを表示(つまりネィティブアプリの中にはViewもLogicもほとんどない)して配布自体はネィティブアプリというものをハイブリッドアプリと称するそうです。

このアプリの利点はちゃんと調べていませんが、Webアプリに対してWebViewを通していろいろ操作で来たり、ブラウザで表示していて戻るボタンとかURL欄をどうにかしたいとかブラウザの外観にしたくなかったりとか、ブックマークしてもらうんじゃなくてアプリインストールしてアイコンをメニューに表示したいとかまあいろいろありそうです。

欠点としては当然WebViewの中で表示しているWebアプリが主体なので、まあ、Webアプリの制限は若干緩和されるけれど基本はWebアプリでできることしかできないと思うくらいが爾来踏まなくてよさそうな気がします。まあ、具体的な地雷がなんなのかまでは深追いしてませんが。

で、ちょっとXamarinで作ってみました。これだけでも大変でした。

 

ということで、Hallo Worldはやらずに

「はじめてのXamarinアプリ」

始まるよ!

 

私の周りだと「古いAndroidは特にサポートしなくていいじゃないかな?」的な雰囲気もあるので「Ice Cream Sandwich」なアプリとして作成します。このテンプレートを使うとAPIレベル15、Android 4.0.3に相当します。

image

 

初期状態のプロジェクト構成は次のような形になります。

image

 

Resources\Layoutの中に、いわゆるViewが入ります。形式はAXMLというやつでXAMLよりも正直しょぼいです。

Activity1.csが画面に対するコードビハインドを記述しているところになります。

 

なんとなくしっくりこないので、ちょっと名前を変えてみましょう。ついでに場所なんかも変えてみたりして。

image

なんとなく普通のC#アプリっぽくなりましたよね?

 

あと、設定しなくても動作しますが、プロジェクトのプロパティで[Android Manifest]の[Application name]あたりも設定しておきましょう。

image

 

それではMain.axmlに画面デザインをしてみましょう。テンプレートから作成された直後にはボタンが1つだけある画面になっています。

image

 

まずはボタンを削除してWebViewを張り付けてみましょう。

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <WebView
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:id="@+id/LocalWebView" />
</LinearLayout>

image

 

もちろんコントロールについてはプロパティウィンドウにプロパティが表示されます。

image

ただし、プロパティとメソッドが分かれていなくて1リストに両方混在しています。このあたりは改善して欲しいですね。

 

最後にコードビハインド側に表示するWebアプリのURLを設定してみましょう。ここが意外と情報が少ないのと、公式オンラインヘルプが分かりづらかった部分になります。

using Android.App;
using Android.OS;
using Android.Views;
using Android.Webkit;

namespace AndroidHybridSample
{
    [Activity(Label = "AndroidHybridSample", MainLauncher = true, Icon = "@drawable/icon")]
    public class Main : Activity
    {
        protected override void OnCreate(Bundle bundle)
        {
            base.OnCreate(bundle);

            RequestWindowFeature(WindowFeatures.NoTitle);
            SetContentView(Resource.Layout.Main);

            WebView localWebView = FindViewById(Resource.Id.LocalWebView);
            localWebView.SetWebViewClient(new CustomWebViewClient());
            localWebView.LoadUrl("http://hatsune.hatenablog.jp/");
            localWebView.Settings.LoadWithOverviewMode = true;
            localWebView.Settings.UseWideViewPort = true;
            localWebView.Settings.JavaScriptEnabled = true;
        }
        private class CustomWebViewClient : WebViewClient
        {
            public override bool ShouldOverrideUrlLoading(WebView view, string url)
            {
                view.LoadUrl(url);
                return true;
            }
        }
    }
}

 

実行してみよう

F5ではなくて[ctrl]+[shift]+[B]でビルドとエミュレータへのデプロイと実行が行われます。

image

Visual Studioエミュレータ間でリモートデバッグが構成されているので、Visual Studio側でブレークポイントをはって動くを調査するようなことも可能です。

 

エミュレータで実行して迷った点/困った点

Xamarinのプロジェクトテンプレートですが、そのまま起動しようとするといくつかエラーがでるパターンがありました。

その時に表示されるダイアログと対処方法を調べてみました。

なぜか、APIレベル10のエミュレータが立ち上がるように設定される

image

Visual Studioのメニューにある起動するエミュレータAPIレベル指定がなぜか「15」にしてたのに「10」に変わっているときが何回かありました。この状態で起動すると、APIレベル15でアプリを作成しているので次のようなエラーダイアログが表示されてエミュレータでアプリが起動しません。

image

対処方法としては、MonoForAndroid_API_15を選択してから保存して再度実行してみてください。

エミュレータが起動しない

image

デバイスがつながっていないかエミュレータが選択されていないと表示されますが、VSを再起動するとなおったりします。

エミュレータが遅いと表示される

image

これは起動時に必ず出てしまうそうなので気にしないのがベストアンサー。

エミュレータでの初回実行が遅い

image

ソースのビルドとか、アプリケーションをデバイスにインストールするのは早いのですが、そのあとに「shared runtime」のインストール、そして極めて時間がかかる「platform faramework」のインストールが影響しています。

 

一度実行してしまえば、次回以降は【そのプロジェクトについては】「shared runtime」「platform framework」のインストールはスキップされるのでかなり改善します。なお、このインストールはプロジェクト単位なので別のプロジェクトの初回実行はやっぱり時間がかかります。

image

パッケージに失敗する

image

過去に1度だけでて再現しないエラーがこのエラーです。たぶん、一度保存してVisual Studio再起動後に読み直して治ったと思います。

エミュレータで実行が始まったようだけれどどうすればいいかわからない

ロック画面になっていたら、丸付き鍵マークを右にスライドしてロックを解除します。

image

 

ロック画面のロックを解けば自動的にアプリが起動します。

image

 

ホーム画面だとしたら下真ん中にある「丸付き三段点々」をタップします。

image

それからアプリ一覧でアプリを探して実行しましょう。

アプリ名はプロジェクトプロパティの[Andoroid Manifest]-[Application Name]で変更できます。省略地はプロジェクト名です。

 

ここまでできたので、次はバージョン情報画面をネィティブ側でつくって表示するところをやってみようかな。