となりのJohnの気まぐれ

気の向くままに

【Uno Platform】端末間でURLを共有するアプリを作った

f:id:newbie29979:20201230195259p:plain

これは何?

まだまだ開発途上のUno Platformを使ったアプリケーション制作日記.
マルチプラットフォームでのアプリケーションビルドが可能なUnoの特性を活かしたアプリケーションをつくりたかった.

https://user-images.githubusercontent.com/12462512/103367377-438bf780-4b08-11eb-9812-a0cdabcd5ab1.png

概要

日々URLに囲まれる我々であるが,URLは逐次クリックする面倒さがある.大半の場合この操作で問題はないのだが,スマートフォン-PC間でわざわざURLを共有して,それをクリックしてというのは面倒に感じる.
スマートフォンとPCは端末やOSが違うという壁を感じる瞬間である.可能であればこの壁を意識せず両方を使いたいと思う.

他にも,どうせなら物理的にローカルなネットワークでそのURLが即時共有されるようになるとより良いのでは,ということでやってみた.
UWP/Android対応のアプリケーション.

ユースケース

  • スマホと母艦PCのURL即時共有:わざわざ「URLを発行してリンクを踏む」という手間がなくなる
  • イベント会場などでの即時公開:QRコードベースでのURLシェア及び自動Openなので,情報の展開が早くできる

構成

f:id:newbie29979:20201230183353p:plain
動作の様子

仕組みは簡単.MQTTを介していずれかのClientがURLを送ると,Subscribeしている端末に通知される.端末では通知されたURLが自動で開く.現在のところの仕様はSubscriberはPublisherでもあるため,逆も然り.
Subscribe(MQTTブローカーのToken登録)はQRコードを介して行う.PCやスマートフォンのカメラで読み取り,そのQRコードは読み取った端末にも表示される.端末を知る物理的範囲でしか構成されないローカルなネットワークでのみ動作する想定.

実際のところ現在の仕様だと信頼関係のあるローカルなネットワークや,個人が使用する端末内のみでの用途になるだろう….
イベント会場で使用する場合など不特定多数が送信する権限を制限するため,PublisherのみにURL送信権は限定するなどちょっとした工夫が必要になってくるかもしれない.

UWPの挙動

Channel Token

UWPのもつjsonにToken情報が記録される.

Publisher

アプリケーションで提供されるテキストボックスのURLを送る.

Subscriber

アプリケーションを起動している間(重要),URIを介して通知されたURLをデフォルトのブラウザで開く.
docs.microsoft.com

Androidの挙動

Channel Token

PreferenceにToken情報が記録される.

Publisher

UWP同様,アプリケーションのURL入力からのpublishも可能.
それ以外のpublishの手段として,インテントで特定のURLについてはアプリ経由でpublishし,Finish()する(ハードコーディングになるのが問題).

     [IntentFilter(new[] { Intent.ActionView },
            Categories = new[] { Intent.CategoryBrowsable, Intent.CategoryDefault },
            DataSchemes = new[] { "http", "https" },
            DataHost = "INTENT_HOST",
            AutoVerify = true
        )]
    public class MainActivity : Windows.UI.Xaml.ApplicationActivity
	{
        protected override void OnCreate(Bundle bundle)
        {
            if (Intent.ActionView.Equals(Intent.Action) && Intent.Data != null)
            {
                var url = Intent.Data;
                var urlSender = new URLSender();
                urlSender.OnStarted();
                urlSender.Connect();
                urlSender.PublishUrl(url.ToString());
                Finish();
            }
            base.OnCreate(bundle);
        }

docs.microsoft.com
詳しく書くと,上記属性はIntentを実現するためのAndroidManifestを自動生成するのに使われるらしい.
docs.microsoft.com
stackoverflow.com

Finish()を使うには下記のサイトが参考になる.
www.ecoop.net

Subscriber

アプリケーションを起動していると(重要),URIを介して通知されたURLをインテント経由でデフォルトのブラウザで開く.これはUWPと一緒.

アイコンとか

今回のプロジェクトは調子にのってアイコンを設定した.設定してみると今までとは異なる雰囲気がして,リポジトリにもライセンスを明記しようと決意.見栄えは大事.MarkMakerでごにょごにょした.
emblemmatic.org

f:id:newbie29979:20201230201403p:plain
GitHubのりどみ.ガラッと雰囲気が変わる.

アイコンの設定はやはり公式サイトが一番参考になる.
docs.microsoft.com

感想

UnoPlatformはまだまだ実装途中のフレームワークで,ファイルの読み込みすら困難など制作中にもいくつかの困難に当たった.基本的な実装方針としてSharedプロジェクトに共通化できるコードを書いて,どうしても避けられないのであればインクルードガードやOSごとのプロジェクトで逐次実装していくのだが,これがなかなか難しい.
インクルードガードの例:

        public URLClientAdapter()
        {
            Prop = new ChannelProperty();
#if NETFX_CORE
            SetProp(File.ReadAllText(@"Assets/ChannelProperty.json"));
#elif __ANDROID__
            var context = Uno.UI.ContextHelper.Current;
            var p = PreferenceManager.GetDefaultSharedPreferences(context);

            var channelInfo= p.GetString("CHANNEL_INFO", "" );
            if(channelInfo != "")
            {
                SetProp(channelInfo);
            }
#endif
        }

インクルードガードはコードの見栄えが汚くなる.プロジェクトごとに分けると想定外のフローが発生する確率が高まる.プラットフォーム固有の対処が不可避な瞬間はどうしてもある.
これらPlatformの仕様に加え,.netが提供する最新のライブラリが非対応であることも多く結構苦労した.QRコードをXamarinで読むとなると定番のZXing.Net.Mobileも私が実装しているときには依存するライブラリが非対応であり,もとのZXing.Netをゴリゴリ動かすしかQRコードを読み込む術がなかった.
d.sunnyone.org
掲載の記事を参考に実装するも,その認識率はかなり悪い.

総括すると,まだまだ制作には安定していないフレームワークの印象.コミュニティはまだ活発で現在バージョンは3.4である.
platform.uno
まだ様子見か.

課題など

実装にあたって遭遇した様々な課題とその解決については,別記事にまとめることにする.
www.rect29.com
www.rect29.com

そのほか

実装で大いに参考にさせていただいた@okazukiさんからTwitterでいいねをいただいた.感謝!
実装の際に大いに参考にしたサイト:
qiita.com
qiita.com

リポジトリ

いつものやつ.
github.com