#define文

#define文は、プリプロセッサディレクティブのひとつで、プログラム中の指定した文字列を別の文字列に置換する・・・。
こういうのをマクロといい、さまざまなマクロを#define文で定義できる・・・。

今回は数値と文字列の定数マクロを定義する・・・。

INT_TENを10、STR_ABCを"ABC"に置換するマクロを定義・・・。

これで、

このプログラム中のINT_TENは10、STR_ABCは"ABC"に置換される・・・。

実行すると、

$ gcc define.c -o define
$ ./define
i = 10
str = ABC
$

となる・・・。

Sample/c/define/define/src/define at master · bg1bgst333/Sample · GitHub

event

delegate型変数をクラスのメンバフィールドに用意しておけば、コールバック関数を実装できる・・・。
ただ、publicでdelegate型変数を公開すると、直接的に中の関数を実行されてしまう・・・。
かといって、privateにすると、実行するハンドラ関数を登録できない・・・。

eventはdelegate型変数へのアクセスをハンドラ登録のみに限定できる・・・。

InputCheckClass.csを用意し、

引数がstringで戻り値がvoidなdelegate、EventDelegateを定義・・・。
(MainClassからも使うのでpublicにしてる・・・。)

コンストラクタに指定された文字列を格納しておくtarget・・・。
InputCheckClassは、このtargetと同じ文字列が入力されたら、イベントを起こすというクラス・・・。
eventの付いたEventDelegate型変数callback・・・。これがイベント用のデリゲート変数・・・。

引数のtargetをメンバに・・・。

InputCheckLoopで、Console.ReadLineで入力された文字列strがtargetと同じかをチェック・・・。
もし同じなら、strをcallbackに渡して実行、それとともにループを抜ける・・・。
つまり、一致するまで無限ループ・・・。

MainClass.csで、

callbackに登録するハンドラEventHandlerは、こんな感じ・・・。
"Hit!: ~"という感じで入力文字列を出力・・・。

Mainでは、

InputCheckClassオブジェクトchkを生成・・・。
対象文字列は"abc"・・・。
chk.callbackに+=演算子で、EventHandlerを登録・・・。
(chk.callbackに括弧と引数を付けて呼ぼうとするとコンパイルエラーになる・・・。)
chk.InputCheckLoopでチェックループに入る・・・。
一致する文字列が見つかって、ループを抜けたら"(End)"を出力・・・。

hoge
foo
bar
abc
Hit!: abc
(End)
続行するには何かキーを押してください . . .

hoge, foo, barは、abcと一致しないので、EventHandlerの処理は起きない・・・。
しかし、abcを入れると、"Hit!: abc"と出力して、このループは終了・・・。"(End)"が出力されて終わる・・・。

Sample/cs/event/event/src/event_ at master · bg1bgst333/Sample · GitHub

WebSettings.getUserAgentString

WebSettingsのgetUserAgentStringでユーザエージェント文字列を取得できる・・・。

WebSettings | Android Developers

メニューアイテムの切り替えを前回やったので、メニューでユーザエージェントの切り替えができるようにする・・・。

main.xmlは、

menu_change_phoneuaとmenu_change_pcuaを追加・・・。

strings.xmlには、

PhoneとPCを選択できるように・・・。

MainActivity.javaで、

uaTypeを切り替えられるように・・・。
CHROME_PC_UAは前にハードコードしたPC用UA文字列・・・。

最初は電話用UAなので、webSettings.getUserAgentStringで取得したUA文字列をuaTypePhoneStringに・・・。
uaTypePCStringはCHROME_PC_UA・・・。
currentUAにもuaTypePhoneStringを・・・。

onCreateOptionsMenuでも、いちおうメニューアイテムの切り替えの処理・・・。
currentUAがuaTypePhoneStringなら、menu_change_phoneuaを非表示にして、menu_change_pcuaを表示にする・・・。
逆にuaTypePCStringなら、menu_change_pcuaは非表示、menu_change_phoneuaを表示・・・。
(現在の状況と逆の項目を選択できるようにする・・・。ややこしいので注意・・・。)

onPrepareOptionsMenuで、メニューボタンが押された時も、切り替えの処理・・・。

Phoneを選択したら、webSettings.setUserAgentStringでuaTypePhoneStringを設定・・・。
webView.reloadでリロード・・・。
currentUAをuaTypePhoneStringにする・・・。

PCを選択した場合も、uaTypePCStringに設定・・・。
reload・・・。
currentUAをuaTypePCStringに・・・。

f:id:BG1:20170308131221p:plain

Yahoo!をひらく・・・。

f:id:BG1:20170308131243p:plain

電話サイト・・・。
ここでメニューボタンを押すと、

f:id:BG1:20170308131311p:plain

GoBackとPCだけ表示・・・。
PCを選ぶと、

f:id:BG1:20170308131348p:plain

PCサイトに切り替わった・・・。
メニューボタンを押すと、

f:id:BG1:20170308131527p:plain

Phoneに切り替わっているので、これを押すと、

f:id:BG1:20170308131452p:plain

また電話サイトに戻った・・・。

Sample/android/WebSettings/getUserAgentString/src/WebSettings at master · bg1bgst333/Sample · GitHub

Activity.onPrepareOptionsMenu

onPrepareOptionsMenuは、メニューボタン(3点リーダアイコンの)が押された時に発生するハンドラで、メニュー表示前の準備段階の処理を行える・・・。

Activity | Android Developers

最初のアイテムの選択によって以降のメニューアイテムの表示/非表示切り替えができるようにしてみる・・・。

res/menu/main.xmlで、

メニュー切り替えアイテムmenu_changeと、切り替える対象となるアイテムmenu_item_a1~menu_item_b3まで用意・・・。

strings.xmlは、

こんな感じ・・・。

MainActivity.javaで、

定数でMENU_TYPE_AとMENU_TYPE_Bを定義し、menuType変数で切り替える・・・。
onCreateOptionsMenuでは、

最初ここに来るので、B1~B3を非表示にすることで、ChangeとA1~A3だけ表示されるようにする・・・。

onPrepareOptionsMenuでは、

menuTypeがMENU_TYPE_Aの時は、itemB1~itemB3を非表示、itemA1~itemA3を表示・・・。
MENU_TYPE_Bの時は、itemA1~itemA3を非表示、itemB1~itemB3を表示・・・。

onOptionsItemSelectedでmenu_changeなら、menuTypeを切り替える・・・。

f:id:BG1:20170308082611p:plain

右上のメニューボタンを押すと、

f:id:BG1:20170308082651p:plain

ChangeとA1~A3が表示される・・・。B1~B3は非表示・・・。
ここでChangeを選択すると、

f:id:BG1:20170308082746p:plain

閉じるが、再びメニューボタンを押すと、

f:id:BG1:20170308083112p:plain

ChangeとB1~B3に切り替わっている・・・。

B1とかを選択しても、

f:id:BG1:20170308083320p:plain

再びメニューボタンを押すと、切り替わらずにB1~B3のまま・・・。
でも、Changeを押すと、

f:id:BG1:20170308083500p:plain

次にメニューボタン押した時はA1~A3に切り替わっている・・・。

Sample/android/Activity/onPrepareOptionsMenu/src/Activity at master · bg1bgst333/Sample · GitHub

マルチキャストデリゲート

デリゲートには、複数のメソッドを登録できる・・・。
これをマルチキャストデリゲートという・・・。

デリゲートの追加は、

<デリゲート変数> += new <デリゲート名>(<実行するメソッド>)

+演算子や+=演算子を使える・・・。
逆に削除は、

<デリゲート変数> -= <削除対象のみのデリゲート変数>

-演算子や-=演算子を使ったりする・・・。

bracketsにBrackets1を呼ぶデリゲートを登録したら、+=でBrackets2を呼ぶデリゲートを追加登録する・・・。

呼び出しは1回だけ・・・。

で、複数のデリゲートが登録されている場合、呼び出しはすべて行われるが、戻り値の結果は一番最後のものが返される・・・。
なので、

Brackets1、Brackets2、どちらも括弧を付けたあとの文字列をいったん出力している・・・。
そのあと、戻り値として返す・・・。

innerStr = (ABCDE)
innerStr = <ABCDE>
str = <ABCDE>

このように、Brackets1、Brackets2、どちらも呼ばれているが、最終的な戻り値strは後に登録したBrackets2のものになっている・・・。

Sample/cs/MulticastDelegate/MulticastDelegate/src/MulticastDelegate at master · bg1bgst333/Sample · GitHub

delegate

デリゲートは、簡単に言うとメソッドを格納する特殊なオブジェクトで、C言語の関数ポインタ、C++の関数オブジェクトのようなもの・・・。

delegate <戻り値型> <デリゲート名>(<引数型> <引数名>);

delegateをつけることで、このような引数型と戻り値型のメソッドを受け取れるデリゲートを定義できる・・・。

戻り値も引数もstringのデリゲートBracketsDelegateを定義する・・・。
これは、引数のmessageの先頭と末尾を括弧(といっても"(~)"とか"{~}"とか"[~]"とか"<~>"とかいろいろ・・・。)で括った文字列を返すメソッドを格納できる・・・。
で渡すメソッドによって括る文字を変えてみる・・・。

Brackets1は、messageを"("と")"で括る・・・。

Brackets2は、messageを"<"と">"で括る・・・。

デリゲートの生成は、こんな感じ・・・。
コンストラクタの引数には、実行するメソッドを渡す・・・。
brackets1は、Brackets1を実行するデリゲート・・・。
brackets2は、Brackets2を実行するデリゲート・・・。

ただ、これだけでは、渡したメソッドは実行されない・・・。

引数の"()"をデリゲートにつけて、中身(実行されるメソッド)が引数付きのメソッドなら引数も渡す・・・。そうすると参照され、渡したメソッドが実行される・・・。

でstr1, str2に括弧で括られた文字列が入ってるかどうか・・・。出力して確認・・・。

str1 = (ABCDE)
str2 = <XYZ>

こんな感じで渡したメソッドが実行されている・・・。

Sample/cs/delegate/delegate/src/delegate_ at master · bg1bgst333/Sample · GitHub

WebSettings.setUserAgentString

WebSettingsのsetUserAgentStringで独自のユーザエージェント文字列を設定できる・・・。

WebSettings | Android Developers

PCサイトブラウザモードを実装するのに使う・・・。

PC版Chromeのユーザエージェント文字列を、

Google Chrome-49.0.2623.87でのUser Agentの設定変更 - Qiita

ここを参考に調べたら、

Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36

だったので、MainActivity.javaで、

webSettings.setUserAgentStringで上のユーザエージェント文字列をセット・・・。

f:id:BG1:20170304134323p:plain

Yahoo!をロードすると、

f:id:BG1:20170304134349p:plain

PC版のサイトが表示された・・・。

Sample/android/WebSettings/setUserAgentString/src/WebSettings at master · bg1bgst333/Sample · GitHub