2022/04/28 初めてのスマホ3
前回の6節の中で「Android には Windows のスタートアップに対する機能が見当たらない」と述べたが見つけた。
他のスマホではわからないが、ColorOS バージョン11 では「設定」−「アプリ管理」−「自動起動アプリ」の中で、当該アプリに対するスイッチをONにすればよい。
「Japan Wi-Fi auto-connect」はこれにより常駐させることに成功した。スマホを再起動した後でも自動実行を確認している。
この件が他のスマホでの動作が保証できないというのが、オープンソースの欠点だと思っている。
バージョンの違いなのか、ColorOS の違いなのかがわからないが、余りに色々なバージョンがある。
スマホ初心者なので、操作がわからないときはインターネットで調べるのだが、微妙に操作方法が違っているので相当迷う。
Windows の場合は、操作の不明点はインターネットで調べれば余り迷うことはない。
また Android に比べて Windows のバージョンはそれほど多くはないので検索文字列の先頭に「Windows 10 ...」等とすればよい。
Android の開発はクラスがいっぱい出てきてよくわからないので、更にクラスで覆ってみようと考えた。
そもそもクラスというのは、パッケージ化して中身をブラックボックス化するというのが本来の機能なので、
クラスを、自分流に作ってしまえばそれほど迷わなくなるのではないかと考えた。
まあ練習問題としては手ごろだと思ったのもあった。
まずは一番使うものを考えてみた。
MessageBox 関数は作者の公開ソフトは7万ステップ程あるが、検索するとその中で 558 カ所あった。
よって MessageBox 関数をクラス化してみようと考えた。
通常考えられる作り方は以下の通りである。
public final class MsgBox
{
//---------------------------------------------------------------------------------------------
public enum Type{NoButton, Normal, Alert, OkCancel, YesNo, YesNoCancel}
public enum Answer{Error, None, Ok, Cancel, Yes, No}
//---------------------------------------------------------------------------------------------
public static Answer Show(AppCompatActivity aca, String msg, Type type)
{
メッセージボックスの作成
メッセージループによる入力待ち
return ans;//クリックしたボタンにより戻り値を返す
}
//---------------------------------------------------------------------------------------------
}
|
この中で「メッセージループ」の部分はネットで色々検索したのだが、どうやってコーディングしたらいいかわからなかった。
メッセージループのコーディングの方法がわからないので、掲示板で聞いてみた。
得た結論はメッセージループはコーディングできず、システムに制御を戻さないといけないということであった。
つまり MessageBox 関数を呼び出すところでは、必ず一度メソッドを終了し次に実行するメソッドを指定しなければならなくなる。
以下がそのサンプルである。
呼び出し側
...............略.............
MsgBox.Show(this, "テストメッセージ", MsgBox.Type.YesNoCancel, this::MsgBoxResult));
//引数 this::MsgBoxResult の追加
}//ここで一度終了、システムに処理させる
private void MsgBoxResult(MsgBox.Answer ans)
{
//ここで ans に対する処理
}
}
|
MsgBox側
public final class MsgBox
{
//---------------------------------------------------------------------------------------------
public enum Type{NoButton, Normal, Alert, OkCancel, YesNo, YesNoCancel}
public enum Answer{Error, None, Ok, Cancel, Yes, No}
//---------------------------------------------------------------------------------------------
@RequiresApi(api = Build.VERSION_CODES.N)
public static void Show(AppCompatActivity aca, String msg, Type type, Consumer<Answer> nextfunc)
{
if ( aca == null ) { nextfunc.accept(Answer.Error); return;}
AlertDialog.Builder builder = new AlertDialog.Builder(aca);
builder.setTitle("アプリ名").setMessage(msg);
switch(type)
{
case NoButton:
builder.setIcon(R.drawable.normal);
break;
case Normal:
builder.setIcon(R.drawable.normal).
setNeutralButton(R.string.ok, (d, w) -> nextfunc.accept(Answer.Ok));
break;
case Alert:
...............中略.............
break;
default:
nextfunc.accept(Answer.Error);
break;
}
builder.create().show();
}
//---------------------------------------------------------------------------------------------
}
|
private なメソッドの数が多くなりそうである。
メッセージループを公開しないのはセキュリティ上の理由かもしれない。
そもそも Windows のメッセージループの中を流れるメッセージは、当該ソフトのメッセージだけではない。
Visual Studio には Spy++ というツールがあり、実行されているすべてのソフトの情報を取れ他のソフトに対するメッセージも取得できる。
例えば「Cmd Process Terminater」は、実行している他のソフトに影響を与えることができる。
そのようなこと禁止するためなのかもしれない。
Google によるソフト公開の審査は甘いと聞いているが、
そうやってセキュリティを確保しているからなのかもしれない。
結局 MsgBox クラスの最終仕様は以下にした。
/**
* MsgBox.Show 使用法
* MsgBox.Show(AppCompatActivity aca, String msg, Type type,
* Runnable nextfunc1, Runnable nextfunc2, Runnable nextfunc3);
* @param aca は親アクティビティ
* @param msg は表示メッセージ
* @param type は MsgBox のタイプ。これ以降は引数を省略できる。
* type を省略したときは type == MsgBox.Type.NoButton とみなす
*
* type == MsgBox.Type.NoButton
* のときは nextfunc1 から nextfunc3 は省略すること
*
* type == MsgBox.Type.Info または MsgBox.Type.Alert
* のときは nextfunc2 から nextfunc3 は省略すること
* nextfunc1 が"ok"ボタンをタッチしたときの処理になる
* nextfunc1 も省略でき、その場合は何もしない
*
* type == MsgBox.Type.OkCancel または MsgBox.Type.YesNo
* のときは nextfunc3 を省略すること
* nextfunc1 が "ok" または "はい" ボタンをタッチしたときの処理になる
* nextfunc2 が "キャンセル" または "いいえ" ボタンをタッチしたときの処理になる
* nextfunc1, nextfunc2 も省略でき、その場合は何もしない
* type == MsgBox.Type.YesNo の時はダイアログ外側タッチでのキャンセルを許さない
*
* type == MsgBox.Type.YesNoCancel
* のときは
* nextfunc1 が "はい" ボタンをタッチしたときの処理になる
* nextfunc2 が "いいえ" ボタンをタッチしたときの処理になる
* nextfunc3 が "キャンセル" ボタンをタッチしたときの処理になる
* nextfunc1, nextfunc2, nextfunc3 も省略でき、その場合は何もしない
*
* 使用上の注意
* この呼出しの後、呼び出したメソッドを終了し、システムに処理させること。させないとMsgBoxは表示されない。
* 例えば nextfunc2 で処理をし nextfunc1 で何もしない場合は nextfunc1 に MsgBox::NullFunc を指定する
* 上記で余計な nextfunc? を指定した場合は "Parameter Error" という例外を発生する。
*/
|
もちろん、とりあえずの仕様であって気分によって変わるかもしれない。