■Androidのカメラ一覧取得

先日、「QRコード読取→URL開く」を作ったのですが、カメラの取り扱いが面倒です。

最近のスマホは、カメラが複数搭載されています。なので、どのカメラで読み取るのか?という選択をしなければいけません。

基本的に、デフォルトは背面になると思うのですが、そうはならない機種もあります。結局、”back”という文字が含まれるかどうかで判断するようにしたのですが、背面カメラも複数あります・・・・。😔

他にも、解像度の違いも機種によってばらばらですし・・・・。

国内では現在、iPhone 50%、Android50%くらいのシェアでしょうか。Androidの場合、少し前のミドルクラスの機種に合わせるのが妥当かと考えています。🤔

■QRコード読取→URL開く

スマートフォンで、QRコードを読み込んで、別の案内サイトを開くことがよくあるので、WEBアプリで作成しました。

以前作成したバーコードテストをそのまま流用しました。これなら、スマホにアプリを入れる必要がありません。こういうスマホアプリは、宣伝だらけですからね。

QR to URL

スマートフォンのWEBブラウザで、ショートカットを作成しておけば、いつでも使用できます。

■WEBアプリJAN,QRコード読み取り

先日作り始めたWEBアプリですが、バーコードの読み取りをテストしてみました。以前、Blazor WebAssemblyでバーコードの読み取りアプリを作成したのですが、今回は、Blazor Serverアプリで新たに作り直しました。

試すには、下記URLよりログインして最初の画面の「JAN,QR読取テスト」をクリックしてください。

JAN13,JAN8とQRコードのみ読み取るように設定してあります。「SCAN」ボタンをクリックすると読み取りを開始。「STOP」ボタンをクリックすると、終了します。

動作確認は、iPhone SE2(iOS18) , Kyocera TORQUE G04(OS10)です。PCではスマホと違って背面カメラというものが無い為、現状、対応しておりません。(・・・時間があったら対応予定・・・)

スマホのカメラでいろいろバーコードを読み取ってみましたが、比較的QRコードは読み取りがいいです。まあ、当然と言えば当然ですよね。JANコードは、白黒は読めますが、それ以外は読み取りがよくないですね。また、白枠の余白が小さいとダメです。そこはレーザー式と比較できないので仕方ないですが・・・。

ただ、カメラ性能も上がってきており、オートフォーカスも良く働くので、最近のスマホは、100%ではないにしろ、商品の90%は読めるのではないでしょうか。

スマホで、バーコードシステムを作るならやはり、QRコード一択ですね!

■WEBシステム開発

「Google Play」にアプリを投稿していましたが、古い端末向けのアプリは排除されてゆく運命にあります。それでたどり着いたのが、WEBアプリでモバイル端末向けのアプリを開発するという方法です。業務用に実際に開発はしていますが、WEBアプリの場合、iPadくらいの画面サイズなら実用的かと思います。スマホだと画面も狭いですし、スペックの低い機種では、バーコード読取時のカメラ性能が不十分だったり、文字入力がやりにくかったり、問題が多いです。Panasonic製のToughPadのような業務用スマホを使う手はありますが、お値段が・・・。😔

今後はモバイル端末でもPCでも使用でき、長く使えるアプリをめざして、Webアプリ開発も進めて行こうと考えています。特定のユーザー向けには開発していますが、一般向けとなると、シンプルさと汎用性を考えないといけないです。また、アプリ開発以前にユーザー認証の問題があります。🤔

とりあえず、一歩踏み出そうと、ユーザー登録&認証画面を作ってみることにしました。

https://mblsta001.azurewebsites.net

①ログインページ

②新規ユーザー登録ページ

社内システムだと、会社のサーバーからAD認証などを使用できるので、Blazorプロジェクトのサンプル通りコーディングするだけでOKです。また、ユーザー管理はサーバーの管理画面でやっているので、社内システムでは、作る必要もありません。なので、その代わりの物を自作しなければなりません。

今回作成した仕組みは、クラウドのデータベース(Azure SQLServer)に、ユーザー情報を持たせる仕組みです。一つのシステム内でも、ユーザーIDでデータを切り分けることで、同時に複数のユーザー運用が可能になります。どのSNS(FacebookやLINEとか)も同じ仕組みだと思いますが・・・。

③正常に認証されるとこの画面になる。

予算の関係で、Freeプランの為、1回目でSQL Serverに接続できない(sleep状態)場合がありますが、少し待って再度「ログイン」するとSQLサーバーのユーザー情報と照合して、この画面になります。

 

ご興味がありましたら、適当に登録して頂いて構いません。また、入力された情報を他社や他のサービスに使用することは決してありません。

 

プライバシーポリシー (mobile-sta.com)

■アジャイル開発

短期間で社内システムを開発するには、

クラウドサービスに合わせて、社内の業務を変える。顧客に渡す帳票類などは、別途開発。

クラウドサービスと連携してアジャイル開発。ランニングコストが許す限り、クラウドサービスを有効活用。

何度も会議を重ねて、詳細な仕様書を作成している間に、環境はどんどん変化して行ってしまいます。現場の要望は、毎週のように、常にレベルアップしてゆきます。同じやり方で、1年以上やっているような時代ではありません。

昔のシステム切り替えは、10年くらいだった気がしますが、現在では5年でも長すぎると思います。扱うデータ量が桁違いに増えているので、スマホでも同じですが、5年前のシステムは、だんだんと力不足になってゆきます。(インフラも含めて全体的に)

従来型(ウォーターフォール型開発)の「要求定義」~「概要設計」~「外部設計」~「内部設計」~「プログラミング」~「単体テスト」~「デバッグ」~「結合テスト」~「システムテスト」~「受け入れテスト」をやっていたら、一体、何年かかるかわかりません。まして、うまくゆくかもわからないのに・・・。

古いシステムのリプレイスを何度もやったことがありますが、はっきり言って、仕様書は無いよりましなくらいです。とにかくソースを見て、実際にどうなっているのか、動かしてみて、想定通りなのかを確認しないとダメです。自分でソースを解析しないとダメです。人が書いたものですから、想定外の未知のバグが出てきます。要するに、他人が書いたものをそのまま信じてはダメです。

また、仕様書より、現場の担当者に聞いた方が正解です。当初と運用も変わってたりしますから。これを言うと、理屈では仕様書が正解というのが正しいのかもしれませんが、仕様書が間違っている場合もあるのです。

制御系の設計の場合は、確かに「ウォーターフォール型」でないとまずいです。(若い頃に、電気制御システム設計をやっていたので) なので、あくまで、ソフトウェアだけのシステムの場合、アジャイル開発が今の時代には向いていると思います。

 

■WEB/DESKTOPアプリ開発、どれだけ違う? 🤔

表題の件、業務アプリ開発専門&Microsoft信者の視点でお話しします。

①使う側の視点での違い。
🖥 DESKTOPアプリ: 
・.Net Runtimeをインストールすれば、Windows,Linux,iOSで動きます。
・プログラムは、ローカルPCで実行されます。
・プログラムをインストールする必要がある。

🌐 WEBアプリ:
・EdgeやChrome、SafariのWEBブラウザー上で動きます。
・プログラムは、WEBサーバー上で実行されます。(WEBブラウザー内で実行する部分もあり)
・プログラムをインストールする必要は無い。

②開発側の視点での違い。
🖥 DESKTOPアプリ:
・DESKTOPアプリ開発者が開発。
小規模システム向け
・DBへの接続の認証などは必須。
・テスト環境は構築しやすい。
・プログラムソース全体の量は、WEBアプリより少なくなる。
・ユーザーの要望は殆ど実現可能。 😀

🌐 WEBアプリ:
・WEBアプリ開発者が開発。(フロントエンド開発者、バックエンド開発者で別々が基本?)
大規模システム向け
・WEB上にデータが流れるので、ログイン時やデータ接続時の認証は必須。 (AzureのようなWEBサービスを使用するのが必須。)
・テスト環境の構築には、若干手間が必要。
・プログラムソース全体の量は、DESKTOPアプリより多くなる。バックエンドとフロントエンドの別々の開発が必要な為。
 1)バックエンド:サーバー内で動く部分。
2)フロントエンド:WEBブラウザー内で動く部分。
 ↑WEBアプリの構造上、ここは変わらないと思います。
・WEBブラウザーの制限上、できないことが多々ある。 😢

・DeskTopアプリ: ローカルPCで実行するプログラムのみ。

・WEBアプリ: サーバー側とローカル側の2つのプログラム。
★この違いはその後の保守の容易さにも影響してきます。

業務アプリ開発 WEB/Desktop?

■社内向け業務アプリ開発 >「①デスクトップアプリ」 or 「②WEBアプリ」どっちがいい? 🤔

表題の通り、社内向け業務アプリ開発で、そもそも「 🖥 デスクトップ/ 🌐 WEB」で悩むところだと思います。
私の個人的な認識は以下の通りです。
(ちなみに私は業務アプリ開発専門&Microsoft信者ですので。 😊 )

①🖥デスクトップアプリ: 
<メリット>
・アプリの柔軟性が絶大。ローカル環境での他のシステムとの接続が自由。
・動作が軽い。(ローカルPCで動く為)
・画面の設計が自由。操作性がよく直感的に使える。

<デメリット>
・新規・更新の配布の際、自動的にダウンロードするメニューなどを用意する必要あり。
※共有フォルダーなどから、随時ダウンロード。
・社外の人にプログラムを共有するのに、手間が掛かる。
※SharePointなどで、共有etc。

②🌐WEBアプリ:
<メリット>
・Azure Webアプリのように、WEB上に公開できるので、配布が楽。
・不特定多数のユーザーの使用に向いている。
・プログラムの入れ替えが楽。(ただし入れ替え時、一時的にサービスが使えない)

<デメリット>
・WEBなので、セキュリティ対策が必要。(IP制限、AzureAD認証など)
・起動時の認証と、ページ読み込みで、時間が掛かる。
・WEBアプリなので、WEBシステム上の制約が多い。
 ※他のシステムとの連携がやり難い。
・WEBサーバーのスペックがそれなりに必要で、ランニングコスト大。

★社内のユーザーに、同じプログラムを、「①デスクトップ版」と「②WEB版」の両方を作って、どちらが使いやすいか聞いてみました。

私も当然予想はしていましたが、①デスクトップ版の方でした。

試したプログラムは、照会系でデザイン的には全く同じものでした。
(なので、私のWEBのデザインが悪かったというのは無しです。 😓 )

特定の業務向けのアプリの場合は、WEBよりデスクトップアプリの方が向いているようです。 😊
※ちなみに、iPadでやる時は、Webアプリ(Blazor)で開発しています。


#社内システム開発 #VisualStudio

DeskTopで、自作ComboBox!

Desktopアプリ開発で、一番悩むのが、dataGridView関係とcomboBoxかと思います。今回は、コンボボックスの一例を紹介したいと思います。WinFormsには、有料のコンポーネントが数多くありますが、結構なお値段なのと、私の長年の経験として、意外とバグがあったりして、それを補完しながらの開発も結構、工数が増えます。

今回は、コンボボックスについて1パターンを紹介したいと思います。3列のコンボボックスで、データをList<DataCombo>形式で渡して、戻り値として、選択したID(1列目)とNAME(二列目)を取得するユーザーコントロールを作りました。(下記イメージ)

CustomCombo.cs (ユーザーコントロール)クラスを一つ作成します。

↓ユーザーコントロール(コンボボックス)のClassソース

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;

namespace WinForms01
{
    /// --------------------------------------------------------------------------------
    /// <summary>
    /// 作成: モバイルステーション 2024.02.23 M.SAGARA
    /// </summary>
    /// --------------------------------------------------------------------------------
    public partial class CustomCombo : UserControl
    {
        private System.Windows.Forms.TextBox textBox;
        private System.Windows.Forms.Button dropDownButton;
        private Form dropDownForm;
        private DataGridView dataGridView;

        public string sNAME = "";

        // カスタムイベントの定義
        public event EventHandler TextBoxTextChanged;

        /// --------------------------------------------------------------------------------
        /// <summary>
        /// コンストラクター
        /// </summary>
        /// --------------------------------------------------------------------------------
        public CustomCombo()
        {
            InitializeComponent();
            InitializeCustomComboBox();
            InitializeDropDownFormWithDataGridView();
            // dataGridView.CellClickイベントを購読
            this.dataGridView.CellClick += MyTextBox_TextChanged;
        }

        /// --------------------------------------------------------------------------------
        /// <summary>
        /// 外部からデータを受け取るためのメソッド 
        /// ※DataCombo (Id,Name,Descripton)
        /// </summary>
        /// <param name="items"></param>
        /// --------------------------------------------------------------------------------
        public void SetData(List<DataCombo> items)
        {
            dataGridView.DataSource = items;
            dataGridView.Refresh();
        }

        // TextBoxのTextChangedイベントハンドラ
        private void MyTextBox_TextChanged(object sender, EventArgs e)
        {
            // カスタムイベントを発火
            TextBoxTextChanged?.Invoke(sender, e);
        }
        // TextBoxのテキストを外部から取得するためのプロパティ
        public string TextBoxText
        {
            get { return textBox.Text; }
            set { textBox.Text = value; }
        }

        private void InitializeCustomComboBox()
        {
            // TextBoxの設定
            textBox = new System.Windows.Forms.TextBox
            {
                Dock = DockStyle.Fill,
                ReadOnly = true
            };
            this.Controls.Add(textBox);

            // ドロップダウンボタンの設定
            dropDownButton = new System.Windows.Forms.Button
            {
                Dock = DockStyle.Right,
                Text = "▼",
                Width = 24,  // ボタンの幅を24ピクセルに設定
                Height = 24
            };
            this.Controls.Add(dropDownButton);
            dropDownButton.Click += (s, e) => ShowDropDownForm();

            // コントロールの高さ調整
            // ボタンの高さを調整する場合は、CustomComboBoxControlのサイズ調整を行う
            this.Height = textBox.Height; // コントロールの高さを調整
        }

        private void InitializeDropDownFormWithDataGridView()
        {
            // dataGridViewの設定
            dataGridView = new DataGridView
            {
                Dock = DockStyle.Fill,
                SelectionMode = DataGridViewSelectionMode.FullRowSelect,
                AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells,
                AllowUserToResizeRows = false,
                RowHeadersVisible = false, // 行ヘッダーを非表示に設定
                ReadOnly = true,
                AllowUserToAddRows = false
            };
            // DataGridViewの行のデフォルトの高さを設定
            dataGridView.RowTemplate.Height = 18;

            dropDownForm = new Form
            {
                FormBorderStyle = FormBorderStyle.None,
                StartPosition = FormStartPosition.Manual,
                Size = new Size(300, 300),  // 初期サイズ設定
                TopMost = true
            };
            dropDownForm.Controls.Add(dataGridView);
            dropDownForm.Deactivate += (s, e) => dropDownForm.Hide();
            dataGridView.CellClick += DataGridView_CellClick;
        }

        /// --------------------------------------------------------------------------------
        /// <summary>
        /// dataGridViewの部分が表示されるときの、イベント
        /// </summary>
        /// --------------------------------------------------------------------------------
        private void ShowDropDownForm()
        {
            // 現在のスクリーンの作業領域を取得(タスクバーなどを除いた領域)
            Rectangle screenWorkingArea = Screen.GetWorkingArea(this);

            // ComboBoxのスクリーン上の位置を取得
            Point comboBoxScreenLocation = this.textBox.PointToScreen(Point.Empty);

            // Formの予定表示位置(ComboBoxの直下)を計算
            int formX = comboBoxScreenLocation.X;
            int formY = comboBoxScreenLocation.Y + textBox.Height;

            // Formの予定表示位置が画面下からはみ出るかどうかを確認
            bool isBelowScreen = (formY + dropDownForm.Height) > screenWorkingArea.Bottom;

            if (dropDownForm.Visible)
            {
                dropDownForm.Hide();
            }
            else
            {
                if (isBelowScreen)
                {
                    // 画面下からはみ出る場合、FormをComboBoxの上に表示
                    formY = comboBoxScreenLocation.Y - dropDownForm.Height;
                }

                // Formの位置を設定して表示
                dropDownForm.Location = new Point(formX, formY);
                dropDownForm.Show();
            }

            // dataGridViewの列幅の計算
            int totalWidth = 0;
            foreach (DataGridViewColumn column in dataGridView.Columns)
            {
                totalWidth += column.Width;
            }
            dropDownForm.Width = totalWidth + 20;
        }   // EOF ShowDropDownForm

        /// --------------------------------------------------------------------------------
        /// <summary>
        /// コンボボックスの行選択時、イベント
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        /// --------------------------------------------------------------------------------
        private void DataGridView_CellClick(object sender, DataGridViewCellEventArgs e)
        {
            if (e.RowIndex >= 0)
            {
                if (dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value != null)
                {
                    // テキストボックスに選択値のセット
                    //textBox.Text = dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value.ToString();
                    textBox.Text = dataGridView.Rows[e.RowIndex].Cells[0].Value.ToString();

                    sNAME = dataGridView.Rows[e.RowIndex].Cells[1].Value.ToString();
                }
                dropDownForm.Hide();
            }
        }
    }   // EOF Class
}   // EOF namespace

Form(コンボボックスを配置した)のソース

        /// --------------------------------------------------------------------------------
        /// <summary>
        /// フォーム読み込み時、イベント
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        /// --------------------------------------------------------------------------------
        private void FrmMain_Load(object sender, EventArgs e)
        {
            // コンボボックスのデータの準備
            List<DataCombo> items = new List<DataCombo>();
            for (int i = 0; i < 100; i++)
            {
                DataCombo row = new DataCombo
                {
                    Id = i.ToString("D4"),
                    Name = "Item " + i.ToString(),
                    Description = "Description " + i.ToString()
                };
                items.Add(row);
            };
            customCombo1.SetData(items);

            boLoading = false;
        }

        /// --------------------------------------------------------------------------------
        /// <summary>
        /// コンボボックスで、行選択時イベント
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        /// --------------------------------------------------------------------------------
        private void customCombo1_TextBoxTextChanged(object sender, EventArgs e)
        {
            // コンボボックスで、選択された行の、2列目の取得
            lblComboName.Text = customCombo1.sNAME;
        }

開発環境の選択について

■開発言語を学ぶ以前の問題として、開発環境として
一体どれを選べば良い? 🤔という疑問があります。

・参考に2024年02月現在、私が業務系アプリ開発で使用している主な開発環境を紹介させて頂きます。
(私が昭和生まれの Microsoft信者であることを先に言っておきます!)
 多分、下記の環境は現在のメジャーかと思います。
 細かい説明は省略しますが、目的によって、それぞれ使い分けています。

①Windows Desktop用: <–デスクトップで、レスポンス重視
 •C# .Net framework (Win Forms) <–従来のシステムサポート
 •C# .Net6(Win Forms)
②Azure Web App用: <–WEBで配布が楽
 •Asp.Net 4.8(Web Forms) <–従来のシステムサポート
 •Asp.Net Core Api(C#) サーバー側 (↓のBack-End 親
 •Blazor Web-Assembly(C#.Net)クライアント側 (↑のFront-End 子

  •Blazor Server(C#) <– (Back-End/Front-Endに分けたくない場合)
③Azure Console App用: 主に夜間バッチ処理
 •C# .Net6
④Azure SQL Database(データベース)
 •現在は、Azure SQLメイン。(その他: Oracle<-ユーザーにより)

↑言語は、現在C#.Net5~C#.Net8へ移行中。
(C#.Net8に手を出すのはまだ、少し早いかも)
.NetFramework4.8は、Windows OSにあらかじめインストールされており、まだまだ現役。ただ今後は、.Net( 旧.Net Core)が最終的に継続サポートされる。

■プログラミング歴30年続けてきて、思う事。
・開発の言語仕様、コンポーネントも毎月のようにバージョンアップしています。サポート切れにならないように、常に新しいものを試して次に繋げていかないと行けません。
・ また、⏳ 時間には限りがあるので、選んで学ばないといけません!
何でも手を出すべきではないです。
今までやってきたことを継続しながら、次に学ぶ物を決めるのが無難。
・そして大事なのは、トライエラーの繰り返しです! 😉