トップ・ページの表示 注意書きの表示 掲示板に書き込む前に必ず この ”注意書き”を お読み下さい.

"伊邪那"

   
   

ページの表示順:{ 新しい順/ 古い順}.
初期・ページの表示・位置:{ 先頭ページ/ 末尾ページ}.
1ページ内のスレッド表示数:











<Number>: [00000852]  <Date>: 2015/01/11 00:50:41
<Title>: 「Java SE JDK」、「ADT Plugin、Android SDK」のダウンロードとインストールなど
<Name>: amanojaku@管理人



Java SE Development Kit 8
「Java SE(Java Platform, Standard Edition) Development Kit 8」
http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html

↑(サーバー側のアプリ開発はできないが)「Java SE Development Kit 8」でも"Android"用アプリの開発なら特に問題は無いのではないかと思われる。

Java EE Development Kit 7
「Java EE(Java Platform, Enterprise Edition) SDK(Software Development Kit) 7 with JDK(Java Development Kit)」
http://www.oracle.com/technetwork/java/javaee/downloads/java-ee-sdk-7-jdk-7u21-downloads-1956231.html

↑もし、「Java 7 (Version 1.7)」系でも良いのなら、こちらの「Java EE(Java Platform, Enterprise Edition)」もあるが、すでに Java 8(Version 1.8)系がインストールされている場合はウマくインストールできないかもしれない。
(現時点で) JRE の正式版の Version は Java 8(Version 1.8) となってるので、わざわざ古い Version を使う必要もないだろうけど…。

Oracle. Java Technology Products.
http://www.java.com/ja/download/manual.jsp

↑(現時点で) JRE 正式版の Version は Java 8(Version 1.8) となってる。


「ADT Plugin for Eclipse、Android SDK」のダウンロードとインストールなど

ADT Plugin for Eclipseのインストール
http://www.javadrive.jp/android/adt/
Android SDKのダウンロードとインストール
http://www.javadrive.jp/android/install/index1.html
ADT Pluginのインストール
http://www.javadrive.jp/android/adt/index1.html
SDK ロケーションの設定
http://www.javadrive.jp/android/adt/index2.html
Eclipse ADTでつくるAndroidエミュレータ開発環境構築メモ(Windows)
http://futurismo.biz/archives/2025

現在、(Google が?)「Android Studio」へ完全に移行させたいのか、公式サイトから「adt-bundle-windows〜.zip」がダウンロードできなくなった模様。
下記は当方がアップした「adt-bundle-windows-x86-20140702.zip」(「プレビューに問題が発生しました」と言うエラーが出るかもしれないが無視して良い)。

> 「adt-bundle-windows-x86-20140702.zip」(Windows 32bit版)
> https://drive.google.com/file/d/0BwisuiuM51wiS0w1RVZRVTl3Ykk/view?usp=sharing

「adt-bundle-windows〜.zip」を解凍する場合、ファイル名と同じフォルダーを作らない設定しないと、2重に同じフォルダーが出来てしまうので要注意。
ファイル名と同じフォルダーを作らない設定でルートに解凍しても「ファイル名が長すぎる」と言うエラーが出る場合があるようなのだが、"+Lhaca"アーカイバ(下記参照)ならウマく解凍できるらしい。

> +Lhaca
> http://www.vector.co.jp/soft/dl/win95/util/se130263.html

(あくまでも現時点においての話)「Tools:Android SDK Tools:Rev.23.0.5」を"Rev.24.0.1"に Update すると正常に Project を生成できなくなるようだ、また「Tools:Android SDK Platform-tools:Rev.20」も"Rev.21"に「Android OS 5」も「Android OS 5.0.1」に、「Android OS 4.4W」も"4.4W.2"に、「Extras:Android Support Library:Rev.20」も"Rev.2"に Update しない方が良い雰囲気。
「Android OS 4.4.2」をインストールすると自然に「Android OS 4.4W」が消えるようだが、特に問題は無いような感じ(「Android OS Version 4.4.2 Emulator」を使わないのだったら特に「Android OS 4.4.2」をインストールする必要もないだろう)。
断定はできないが、『「Tools:Android SDK Platform-tools」、「Tools:Android SDK Build-tools」、「Extras:Android Support Library」』の Revision の整数値は「API Level」を表わしているような雰囲気なので「Tools:Android SDK Build-tools」の"Rev.21.x"も Install しない方が良い雰囲気。
もし、Update してしまっいる場合は上記の Update 前のデータ(当方の Windows XP 32bit 環境のデータなので Windows 32bit 環境なら使えるだろうと思われる)"ADT-SDK_WindowsXP-32bit_007.lzh"(1.07GB)を次のアドレス「 https://drive.google.com/file/d/0BwisuiuM51wiU0VmZE1NbjJjM1k/view?usp=sharing 」から(「表示できるプレビューがありません」と言うエラーが出るかもしれないが無視して良い)ダウンロードし、"sdk"フォルダー内のフォルダーを全て削除(ファイルの使用中で削除できない場合は一旦 ログアウトし、またログインしてから削除)し、"sdk"フォルダー内に"ADT-SDK_WindowsXP-32bit_007.lzh"を入れて(ファイル名と同じフォルダー作らない設定で)解凍してやる。
その後、「SDK Manager」で「Deselect All」をクリックしチェックを全て OFF にしてから、「Extras:Google USB Driver」をインストールする。
それで正常に Project を生成できない場合は、<User>内の".android"フォルダーを削除し(<User>は"My Documents"ではない)、新しく空の"workspace"作成し(古いファイルをコピーしない空の状態で)スケルトンを作成し、"appcompat_v7"を選択し"Refresh"([F5]キー)してやる。
また「Android Virtual Device Manager」で作成した「仮想 Device」が「run configurations」:「Target」タブの「仮想 Device」リストに反映されていない場合は、「Package Explorer」ビューの"Project"を右クリックし(ショートカット・メニュー)「Run As」→「Android Application」を実行すれば「run configurations」:「Target」タブの「仮想 Device」リストに「仮想 Device」が反映されるようだ。


(複数の Eclipse がインストールされている場合は)必ず adt-bundle-windows〜.zip で展開された adt-bundle-windows〜 フォルダー内の Eclipse を使用する。
(現時点の adt-bundle-windows〜.zip では)「eclipse」フォルダーに「eclipse.ini」ファイルが有るので、(順番に依存するので)先頭に「-vm」オプションで「JDK(Java Development Kit)」の「Java\jdk〜\bin\javaw.exe」のフル・パスを設定してやる(下記参照)。

-vm
C:\Program Files\Java\jdk〜\bin\javaw.exe


「eclipse.ini」の基本形データをバックアップしておくのも悪くないかもしれない(当方の「eclipse.ini」の基本形データを参考までに下記にアップしておく)。
なお、「eclipse.ini」ファイルは"メモ帳"で開いてはならない、"Unix"系の改行コードと"Windows"系の改行コードとの違いにより、一見 改行してないように表示されてしまう場合があるようだ、次のような Editor なら正常に表示されるようだ。

> MKEditor for Windows
> http://www.vector.co.jp/magazine/softnews/090124/n0901241.html

> EmEditor Free
> https://jp.emeditor.com/text-editor-features/history/emeditor-free/


eclipse.exeの-cleanオプションをショートカットに設定する
http://www.hitachi.co.jp/Prod/comp/soft1/cosminexus/useful/tips/081205_eclipseexe-clean-shortcut.html


「res\layout\activity_main.xml」を開き、下の「Graphical Layout」タブを選択すると、レイアウト・ビルダーが表示される(エミュレータではない)が、ここで「API Level:Android OS Version」を指定でき、使える GUI 部品が変わる(エミュレータのバージョンを指定してる訳ではない)。
ちなみに「Android OS Version 1.x」は指定できない、それは「Version 1.x」は開発できない事を意味しているので、「Android OS Version 1.x」はインストールする必要はない。
「Android OS Version 4.4W」は「Android Wear」と言う「スマートウォッチ(腕時計型ウェアラブルデバイス)」用に開発された Android OS らしいので、「Version 4.4W.x」もインストールする必要は無いような気もするが、(「Android SDK」の Version や環境によって違う場合もあるだろうが)「Android OS Version 5.0」をインストールすると、デフォルトでインストール済の「Version 4.4W.x」の「SDK Platform」が「Not Installed」になって JavaFX 用のプロジェクトに"×"が表示されてしまう場合があるようだ。
その場合、「Version 4.4W.x」の「SDK Platform」を再インストールすれば良いようだが、「Android OS Version 5.0」をインストール時に何回も警告が出る場合があるので、その時は一旦「Android OS Version 5.0」のインストールのチェックを全て OFF にしてから、「Version 4.4W.x」の「SDK Platform」を再インストールし、その後 (未インストールの)「Android OS Version 5.0」をインストールすれば良いようだ。


(Win) x86版Android エミュレータを使えるようにするまで
http://52c.tumblr.com/post/34218675318/win-x86-android

↑下記の措置は必須ではないようで、AVD Managerのリストに"x86"("CPU/ABI"?)のイメージが表示されない場合の措置と言うことらしい。

> android-sdk\add-onsディレクトリに「addon-intel_atom_x86_system_image-intel_corporation-16」というフォルダを作成

(現時点の adt-bundle-windows〜.zip では)「sdk\add-ons」フォルダーに「addon-intel_atom_x86_system_image-intel_corporation-16」というフォルダを作成

> 先ほどのフォルダ内にimagesフォルダとmanifest.iniというテキストファイルを作成

manifest.ini は作成する必要もない雰囲気ではあるが、一応 そのサイトの通りテキストをコピペしておけば良いだろう。

> Android-SDK\system-images\android-16\ 以下を images\ 以下へコピー

(現時点の adt-bundle-windows〜.zip では)「android-16」フォルダーは存在していないので、「sdk\system-images」フォルダー以下を「addon-intel_atom_x86_system_image-intel_corporation-16\images」フォルダー以下へコピー。

> x86\source.properties を manifest.iniと同じ位置に移動します

「x86\source.properties」の所在は不明なのでコピーできない。


Android SDK の高速エミュレータ、使ってますか?
http://www.webtech.co.jp/blog/developer-news/5966/

↑「Android SDK Manager」で「Intel x86 Emulator Accelarator」がインストールできない場合は、他のチェックをハズし、「Intel x86 Emulator Accelarator」単体でインストールしてみる。
仮想化支援機構(Intel(R) Virtualization Technology)を CPU がサポートし、仮想化支援機構を BIOS がサポートし、BIOS で仮想化支援機構をイネーブルに設定してやらないと「Intel x86 Emulator Accelarator」は実行できない。
(現時点の adt-bundle-windows〜.zip では)場所は「sdk\extras\intel\Hardware_Accelerated_Execution_Manager\intelhaxm-android.exe」となってるようだ。


「Android SDK」がアップデートされ、以前の"workspace"との不整合が生じ、新たなプロジェクトを作成するとプロジェクトに×が付く場合があるようだ。
(「Android SDK」のアップデートの場合に限らず) Eclipse の調子が悪くなったら、とりあえず"workspace"を変更し、(古い"workspace"内のデータをコピペしてはならない)スケルトンのプロジェクトが正常に作成できるか試してみる。
それでダメなら「ADT Plugin for Eclipse、Android SDK」の上書き、それでダメなら「ADT Plugin for Eclipse、Android SDK」を削除してから再インストールと言う感じになる(これらの場合も、以前のデータが存在する"workspace"を使用してはならない)。
ちなみに正常に"workspace"をインポートできないような感じ(以前のプログラムを移行したい場合はスケルトンのプロジェクトを作成し、そこにソースをコピペするしかないのか)。

Click to Download. 00000852.0.txt:(Size=471Byte) Name = eclipse.ini 2014.11.23-23.32.txt


<Number>: [00000855]  <Date>: 2015/01/11 01:29:40
<Title>: "Android"用 JavaFX プログラミングで参考にしたサイト
<Name>: amanojaku@管理人



"Android"用 JavaFX プログラミングで参考にしたサイト

クラウドサービスプラットフォーム Cosminexus:Eclipse のエディターで、行番号を表示するには?
http://www.hitachi.co.jp/Prod/comp/soft1/cosminexus/useful/tips/091002_eclipse-show-line-number.html

JAVA > Android開発入門 > エミュレータ > エミュレータの操作方法 
http://it-trick-java.appspot.com/android/c12009/page19005.html

Android versionCodeとversionNameの違い -でじうぃき
http://onlineconsultant.jp/pukiwiki/?Android%20versionCode%E3%81%A8versionName%E3%81%AE%E9%81%95%E3%81%84

↑"versionCode"は"Version"とは別物の「Build No.」ぐらいに思っておいた方が良いだろう。

ソフトウェア技術ドキュメントを勝手に翻訳
http://www.techdoctranslator.com/
マニフェストファイルの使用\起動モードの定義
http://www.techdoctranslator.com/android/guide/activities/tasks-and-back-stack#ManifestForTasks

まずは Hello World を作ってみる
http://seesaawiki.jp/bacchus1225_android/d/%A5%DA%A1%BC%A5%B81

勉強会 / HelloAndroid
http://www.android-group.jp/index.php?%CA%D9%B6%AF%B2%F1%2FHelloAndroid

勉強会 / ボタンをつくってみよう
http://www.android-group.jp/index.php?%CA%D9%B6%AF%B2%F1%2F%A5%DC%A5%BF%A5%F3%A4%F2%A4%C4%A4%AF%A4%C3%A4%C6%A4%DF%A4%E8%A4%A6

表示文字列の設定
http://www.javadrive.jp/android/edittext/index3.html

プログラムから文字列リソースを参照 - 文字列や色のリソース定義 - Android入門
http://www.javadrive.jp/android/values/index3.html

図で理解するActivityのスタック
http://techblog.qoncept.jp/?p=102

アクティビティのライフサイクル
http://www.javadrive.jp/android/activity/index2.html

Androidでゲーム作成(1)
http://d.hatena.ne.jp/shuji_w6e/20090127/1233070723

AndroidのSurfaceViewの基礎
http://qiita.com/croquette0212/items/24dc2b6de3730e831aab

> SurfaceViewの上に普通のUI要素(ボタンとか)を重ねてもOKだけど

"Eclipse"の「Layout Builder」では"SurfaceView"上に(「ボタン、ラベル」などの)UI コンポーネントを重ねる事は出来ない。

描画用スレッドを実装できる SurfaceView の利用方法
http://android.keicode.com/basics/surfaceview-1.php

SurfaceViewならAndroidで高速描画ゲームが作れる
http://www.atmarkit.co.jp/ait/articles/0912/08/news107.html
http://www.atmarkit.co.jp/ait/articles/0912/08/news107_2.html
http://www.atmarkit.co.jp/ait/articles/0912/08/news107_3.html

Eclipse を使用した Android のログ出力
http://ohwhsmm7.blog28.fc2.com/blog-entry-42.html

デバッグログを使いこなす
http://techbooster.org/android/environment/522/

> コマンドラインでのLog確認方法
> Eclipce以外からログを見るには、adbのlogcat(コマンドライン)があります。
> adb logcat

↑"adb"を実行する場合、環境変数の PATH に"adb"への Path を設定するか、実行時に"adb"への Path を指定しなけらばならない。
(現時点の adt-bundle-windows〜.zip では)「〜\sdk\platform-tools\adb.exe」に存在するようだ。
Device を起動する前に「adb logcat」を実行しておく必要があるようだ"-S"オプションで"TAG"名を指定できるようだ(例.「adb logcat -s タグ名」)


logcatがない!消えた!表示されない!
http://blog.livedoor.jp/doizudeseikatu/archives/51643738.html

エミュレーターでの起動
http://www.javadrive.jp/android/distribute/index3.html

エミュレーターの起動とアプリのインストール
http://www.javadrive.jp/android/commnadline/index4.html

↑"start"コマンドに対する PATH の設定は必要ないようだ、(現時点の adt-bundle-windows〜.zip では)「emulator.exe」は「sdk\tools」に、「adb.exe」は「sdk\platform-tools」に有るので、半角";"(セミコロン)で区切りフル・パスで PATH の設定をしてやる。
当方では Emulator が正常に起動できなかったが、Eclipse からの起動でアプリのインストールに失敗した場合に adb は使える。
アプリのインストールに失敗した場合でも、アプリの残骸みたいなモノが残ってる事もあるので、その場合は仮想 Device の Setting(設定) から Application を Uninstall してから adb でアプリをインストールしてやれば良い。
ちなみに、Eclipse ではデフォルトで 「Build Automatically」(自動ビルド)が ON になってるハズだが、どうも(Build だけでは)実行形式は生成されないようだ。

> Windows 環境変数 Path の設定方法
> http://next.matrix.jp/config-path-win7.html


▲注.Eclipse の起動が やたら遅い場合は(何か問題がある可能性があると思われるが)、とりあえず(メニュー・バー)[Project]→[Build Automatically](自動ビルド)を OFF にしてみる、その場合は何か変更したら必ず手動で(メニュー・バー)[Project]→[Build Project]、又は(メニュー・バー)[Project]→[Build All]を実行してやらなければならない(下記「プロジェクトの手動ビルド」参照)。

> プロジェクトの手動ビルド
> http://www.javadrive.jp/eclipse3/step/index5.html


▲注.(Android OS Version 2 Emulator では ActionBarActivity のメニューが表示されず、また Android OS Version 4.x Emulator の起動は やたら重く、また Android OS Version 3.0 Emulator は調子が悪いようなので) Android JavaFX プログラム開発の Minimum Version を「Layout Builder」では「API 8:Android 2.2」、Emulator では(基本的には)「Android OS Version 3.1」とする。
ちなみに当方の仮想 Device の設定は『「5.1" WVGA (480 × 800 mdpi):(AVD_for_5_1_WVGA)」、Target は「Android 3.1 - API Level 12」』、(ActionBarActivity のメニューが表示されないが)グラフィックのチェック用に『「Galaxy Nexus (4.65" 720 × 1280 xhdpi):(AVD_for_Galaxy_Nexus_by_Google)」、Target は「Android 2.2 - API Level 8」』、これらの共通の設定は『Skin は「No Skin」、「Memory Option」:「RAM」は"256"、「SD Card」は「16 MB」、Emulation Options の「Use Host GPU」と言う項目がある場合は"ON"』としている(仮想 Device を設定したり、変更した場合は Eclipse を再起動した方が良さそうな雰囲気)。
なお、"Widget"アプリケーションを起動したい場合は、『「Galaxy Nexus (4.65" 720 × 1280 xhdpi):(AVD_for_Galaxy_Nexus_by_Google)」、Target は「Android 2.2 - API Level 8」』の場合は(充分な「"Widget"アプリ配置用・空き領域」がある)"Home"画面を長押して表示されたメニューから"Widgets"を選択(クリック)し、"Widget"アプリを(長押しではなく)選択(クリック)してやる("Home"画面に配置と同時に"Widget"アプリは起動する)、『「5.1" WVGA (480 × 800 mdpi):(AVD_for_5_1_WVGA)」、Target は「Android 3.1 - API Level 12」』の場合は(画面 下部・中央の)アプリ・アイコンからアプリの選択画面に入って、「Widget Preview」アプリを起動して"Widget"アプリをクリックしてやれば"Widget"アプリを起動できる(これは あくまでも"Widget"アプリの動作確認のためだけで、"Widget"アプリを"Home"画面に配置する事はできないようだ)。
※なぜか当方の実機では ActionBarActivity のメニューが表示されない。
※dp(dip) を考慮してないグラフィック表示などは Version の違いよりも Device の解像度の違いによって見え方が変わってくるので、グラフィック表示などは これらのような解像度の違う Device で見比べてみた方が良いだろう(「dp、解像度」に関しては下記参照)。
通常、アプリのアンインストールは仮想 Device の Setting(設定) から Application を Uninstall しやれば良いハズだが、『「5.1" WVGA (480 × 800 mdpi):(AVD_for_5_1_WVGA)」、Target は「Android 3.1 - API Level 12」』の場合は Application 画面に入れないようだ。
その場合は、まず起動している Emulator(仮想 Device) を修了させてから(Windows の場合)「<User>\.android\avd\<Device>」(<User>は"My Documents"ではない)フォルダー内の「userdata-qemu.img、cache.img」を削除すればユーザーがインストールした全てのアプリが消えるハズ。

> Y.A.M の 雑記帳 Android Dimension 単位
> http://y-anz-m.blogspot.jp/2010/05/androiddimension.html
> Y.A.M の 雑記帳 Android TextView の setTextSize() は sp 単位だよ!
> http://y-anz-m.blogspot.jp/2012/02/androidtextview-settextsize-sp.html
> Y.A.M の 雑記帳 Android dip, dp, から pt, px に変換する
> http://y-anz-m.blogspot.jp/2010/10/androiddip-sp-pt-px.html

> 続・Android端末の画面解像度をまとめてみた はいみっくすわーるど
> http://highmix-w.net/world/blog/?p=316
> 秋葉ちひろのAndroidアプリデザイン入門(5)
> http://www.mdn.co.jp/di/newstopics/29292/?rm=1


▲注.(Windows の場合)"AndroidManifest.xml"に"LF"だけの改行コードが含まれている「ファイル、テキスト・データ」などをコピペすると、layout ファイルのコード・支援機能に(黄色い波線のアンダーラインの警告が出なくなる)障害が発生する場合があるようだ。
ちなみに、(Windows の改行コードは「CR+LF」だが) "AndroidManifest.xml"ファイル内部の改行コードは"LF"となっているようだが(バグか?)、"LF"だけの改行コードが含まれている「ファイル、テキスト・データ」などをコピペしてはいけないと言う意味不明な仕様となっているようだ。
この原因のメボシを付けるまで散々 苦労したが、"LF"だけの改行コードに対応している掲示板に書き込んで(当然、Windows 上で)コピペすると(今までの苦労が嘘のように)簡単に直ってしまった。
"LF"だけの改行コードを「CR+LF」の改行コードに簡単に変換してくれる Editor が有れば良い訳だが、いつも使っている「MKEditor for Windows」(下記参照)で簡単に変換できる事が分かった。
"LF"だけの改行コードが含まれているファイルを「MKEditor for Windows」で開き(警告ダイアログが出るかもしれないが構わず[OK]を押す)、全体を選択しコピーしてやるとクリップボードのデータは既に「CR+LF」の改行コードに変換されているようなので、そのままペーストしてやれば良いようだ。

> MKEditor for Windows
> http://www.vector.co.jp/magazine/softnews/090124/n0901241.html


▲注.layout ファイル自体をコピペすると「R.menu.main」でエラーになる場合があるようだ、(この問題に関しては) layout ファイルを開いてテキストをコピペすれば良いようなのだが、(Windows の場合)"LF"だけの改行コードが含まれている「テキスト・データ」などをコピペすると、layout ファイルのコード・支援機能に黄色い波線のアンダーラインの警告が出なくなる)障害が発生する場合があるようだ(ちなみに、Windows の改行コードは「CR+LF」)。
これも「MKEditor for Windows」からコピペすると直るようだ。

▲注."AndroidManifest.xml"の『<uses-sdk android:minSdkVersion="〜" android:targetSdkVersion="〜" />』は開発環境によって生成されたデフォルト値が推奨されるような雰囲気だ(他のサイトからコードをコピペする場合は とりあえずデフォルト値に置き換えておく)。
当方の"minSdkVersion"のデフォルト値は"8"となっているが、それは"minSdkVersion"が"7"以下だとアプリケーション開発に支障がある事を示唆している可能性も考えられる。

▲注."AndroidManifest.xml"の <service>タグ内で<intent-filter>タグを使うと(コード支援機能による)警告が発生する(バグか?)場合があるようだが、"android:minSdkVersion"の値が"4"以上に設定されていれば問題ない雰囲気。

▲注.「UI(User Interface) Component」の「R Class」に対する(コード支援機能による)警告があっても、無闇に"package"を"import"してはならないようだ。
その場合、"AndroidManifest.xml"内の"package"名の定義との不整合か、"layout"フォルダー内の"xml"ファイルに何らかの問題があると想定される。

▲注.「@string/〜、@dimens/〜、@styles/〜」のような記述はインデックスのようなもので、データの本体は別にある。
そのインデックスは「@ファイル名/インデックス名」のように記述され、「res\values」フォルダー内のファイルが参照されるようだ。

▲注.「run configurations」で明示的に「Android」タブで「アプリケーション、プロジェクト」を、「Target」タブで「仮想 Device」を指定できる、「Common」タブの「Launch in background」のチェックを外すとエミュレータを Foreground で実行(優先順位が上がる?)させる事ができる、ちなみに「Android」タブの「Launch Action」パネルは「Do Nothing」を推奨。

▲注.(「Android」タブの「Launch Action」パネルの「Do Nothing」が ON の場合)[Console](デフォルトの画面構成の場合は下のサブ・ウィンドウ)に下記の2行が表示されるまでは、Android 上に作成されるアプリは実行できない。

> 〜 installed on device
> 〜 Done!

▲注.Android エミュレータでは、(ダブル・クリックではなく)シングル・クリックが基本。
Android エミュレーターの動きがトロイからと言ってボタンなどをユックリおすと"タップ"ではなく"長押し"となってしまう場合があるようなので、素早くクリックしてやる。

▲注.ウィンドウ・下部のサブ・ウィンドウの[Console](タブ)ビューが いつの間にか"DDMS"になっている事があり(下記 画像 参照)、その場合[Console](タブ)ビューにメッセージが表示されず、[LogCat](タブ)ビューもログが表示されないので、"Android"側に設定してやる。
それでも[LogCat](タブ)ビューにログが表示されない場合は下記サイト参照。

> LogCat ( DDMS )
> http://www.7roid.com/basics/kiso_03_5

どうしても[LogCat](タブ)ビューにログが表示されない場合は Eclipse を再起動してみて下さい。

▲注.作成したアプリを(サンプルとしてではなく)正式なアプリケーションとして配布するような場合には、「"Package"名、"Event"の"Filter"用・文字列」などは世界で唯一の Unique な文字列でなければならないのかもしれない。


<Number>: [00000856]  <Date>: 2014/12/28 14:42:15
<Title>: アプリの多重起動
<Name>: amanojaku@管理人



アプリの多重起動

Android アプリでは[Home]キーを押した場合"Stop"待機状態になるようなのだが、(Android 2.2 エミュレータでは そのような問題は起こらなかったのだが)問題は(Android 4.3 の実機で)[Home]キーを押した後 そのアプリを再実行すると前のタスクとは別の さらに新しいタスクが加えられて行くようだ(下記サイト参照)。

図で理解するActivityのスタック
http://techblog.qoncept.jp/?p=102

launchMode="singleInstance"に設定することで起動するインスタンスを1つに限定できる。

『AndroidManifest.xml』の下記の部分を変更する、「<application」ではなく「<activity」である事に注意。

>         <activity
>             android:name=".MainActivity"
>             android:label="@string/app_name" >

下記が変更後、最後の行の末尾の">"(グレーターザン:大なり)記号が付け替えられてる事に注意。

>         <activity
>             android:name=".MainActivity"
>             android:label="@string/app_name"
>             android:launchMode="singleInstance" >


<Number>: [0000085D]  <Date>: 2015/01/08 08:01:25
<Title>: Button イベント (改)
<Name>: amanojaku@管理人



Button イベント (改)

とりあえず、アプリケーション名は"Hello003_JFX"、プロジェクト名は"Hello003_Prj"パッケージ名は"com.example.hello003_pkg"としている、その他はデフォルトでスケルトンを作成。


『src/com.example.hello003_pkg/MainActivity.java』


package com.example.hello003_pkg;

import android.support.v7.app.ActionBarActivity;
import android.content.res.Resources;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;

public class MainActivity extends ActionBarActivity {
    
    String vsDisplayHello;
    String vsMessage = "";
    EditText cetMessage;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        vsDisplayHello = getString(R.string.display_hello);
        
        /* ボタンを取り出す */
        Button cbHello = (Button)findViewById(R.id.cb_hello);
        /* ボタンにリスナーを登録する */
        cbHello.setOnClickListener(new OnClickListener( ) {
            @Override
            public void onClick(View v) {
                vsMessage = vsMessage+vsDisplayHello+"\n";
                cetMessage.setText(vsMessage);
            }
        });
        
        /* エディット・テキストを取り出す */
        cetMessage = (EditText)findViewById(R.id.cet_message);
        
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
    
}


『res\layout\activity_main.xml』


<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context="com.example.hello003_pkg.MainActivity"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" 
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin" >

    <Button
        android:id="@+id/cb_hello"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/cb_hello" />
    
     <EditText
         android:id="@+id/cet_message"
         android:layout_width="match_parent"
         android:layout_height="0dp"
         android:layout_weight="1"
         android:gravity="top"
         android:inputType="textMultiLine" >

    </EditText>
     

</LinearLayout>


『res\values\strings.xml』


<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string name="app_name">Hello003_JFX</string>
    <string name="action_settings">Settings</string>
    <string name="display_hello">Hello world!</string>
    <string name="cb_hello">Hello</string>

</resources>


『AndroidManifest.xml』


<?xml version="1.0" encoding="utf-8"?>
<manifest
    xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.hello003_pkg"
    android:versionName="1.0"
    android:versionCode="1" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="20" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name"
            android:launchMode="singleInstance" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>


<Number>: [00000871]  <Date>: 2015/01/10 00:13:49
<Title>: SurfaceView(2) 改(2)
<Name>: amanojaku@管理人



SurfaceView(2) 改(2)
サンプル動画 http://www.youtube.com/v/-khejT0BwXw&autoplay=1

《参考》

SurfaceView(2) 改(3)
http://artemis.rosx.net/sjis/smt.cgi?r+izanami/&bid+0000083C&tsn+000008F9&bts+2014/10/28%2002%3A03%3A17&


"SurfaceView"の"Destroy"

Android アプリの待機状態には「Pause、Stop」が有り、[Home]キーを押した場合"Stop"状態になるようなのだが、問題は その時(恐らく「onStop(…)」メソッドの実行後)に"SurfaceView"が"Destroy"してしまう事だ。
Android アプリは"Stop"状態から起動する場合、「onCreate(…)」メソッドは呼ばれずに、その代わり「onRestart(…)」メソッドが呼ばれる。
つまり、「onRestart(…)」メソッドを"Override"し そこで"SurfaceView"を"Create"してやらなければならないのだが、「onRestart(…)」メソッドを"Override"できない。
"AndroidManifest.xml"に 何か設定してやるとか書いてあるが、サッパリできん…(^_^;)

後、"SurfaceView"が"Destroy"される前、(恐らく)「onStop(…)」メソッドで"Thread"を破棄し"Canvas"への描画を停止させる必要があるが、当然「onStop(…)」メソッドも"Override"できない。

> "AndroidManifest.xml"に 何か設定してやるとか書いてあるが、サッパリできん

現行バージョンの開発環境ならデフォルトで OK のようだ。
単に「onCreate(…)」メソッドと同じ引数を持つと思い込んで、勘違いしていた。
「onCreate(…)」メソッド以外は引数は無し。

> つまり、「onRestart(…)」メソッドを"Override"し そこで"SurfaceView"を"Create"してやらなければならない

良く考えたら"SurfaceView"を"Create"するのは「onStart( )」メソッドにするべき。

> [Home]キーを押した場合"Stop"状態になるようなのだが、問題は その時(恐らく「onStop(…)」メソッドの実行後)に"SurfaceView"が"Destroy"してしまう

「onStop(…)」メソッドの実行後では無く、「onStop(…)」メソッドの実行・前後のようらしい。


今回、Android 用 JavaFX プログラミングで参考にしたサイト。

アクティビティ - ソフトウェア技術ドキュメントを勝手に翻訳
http://www.techdoctranslator.com/android/guide/activities
Activityのライフサイクル - アンドロイド道場
https://sites.google.com/site/androidappdojo/home/devmemo/memo04
Androidアクティビティのライフサイクル解釈 - clock-up-blog
http://blog.clock-up.jp/entry/2014/03/18/112955

Object (Java Platform SE 6) wait
https://docs.oracle.com/javase/jp/6/api/java/lang/Object.html#wait%28%29
Object (Java Platform SE 6) notify
https://docs.oracle.com/javase/jp/6/api/java/lang/Object.html#notify%28%29

synchronized で何を Monitor に指定すれば良いのか?、恐らく この場合は操作される側の Runnable インターフェイスを継承しているインスタンス(この場合は RunningDriver のインスタンス)を Monitor にするのが良いような雰囲気。

とりあえずアプリケーション名は"A009_JFX"、プロジェクト名は"A009_Prj"、パッケージ名は"com.example.a009_pkg"としている、その他はデフォルトでスケルトンを作成。
ボタン"Accept"(アクセプト)は"Through"(スルー)状態の Runner を再スタートさせる。
ボタン"Through"(スルー)は Runner を"Through"(スルー)状態(runningEngine は動いているが Runner はスルーとなる)にする。
ボタン"notify"は"Wait"状態の Runner を再スタートさせる。
ボタン"Wait"は Runner を"Wait"状態にする。
ボタン"Create"(クリエイト)は"runningEngine"(Thread)を生成しスタートさせる。
ボタン"Destroy"(デストロイ)は"runningEngine"(Thread)を破棄する。


『src/com.example.a009_pkg/MainActivity.java』


package com.example.a009_pkg;

import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView.BufferType;
import android.util.Log;

public class MainActivity extends ActionBarActivity implements 
SurfaceHolder.Callback {

    static final String tag = "Log.Debug"; // フィルタリング用タグ
    static final boolean DEBUG = true; // false; // 
// ↑ この"DEBUG"は予約語では無い、"Java"において"final"(定数)の場合は
// 全部 大文字で記述するの事が推奨されているようだ。
// 「DEBUG=true」に設定すれば「if(DEBUG)Log.i(〜)」によって"LogCat"に出力される事になる。
    
    Thread running = null;
    boolean runningSW = true; // false; // 

    static int appLaunchMode;
    public static final int LAUNCH_CREATE = 1;
    public static final int LAUNCH_RESTART = 2;
    
    MainActivity app;
    int screenWidth, screenHeight;
    boolean surfaceChangedSW = false; // true; // 
    String vsMessage = "";
    EditText cetMessage;
    RunningDriver runningDriver;
    // Canvas canvas; 
    int[] cPalette = {
      Color.RED,Color.YELLOW,Color.MAGENTA,Color.GREEN,Color.CYAN,Color.BLUE };
// ↑ カラーの実態は Color オブジェクトではなく  int。
    
    public abstract class RunnerPrimitive {
        boolean ThroughSW = false; // true; // 
        public void run( ){ }
    }
    public abstract class RunnerFigure extends RunnerPrimitive {
        RunningDriver runningDriver; 
        Color color;
        Paint paint = new Paint( );
        int cx,cy,dx,dy;
    }
    public class RunnerCircle extends RunnerFigure {
        
        int radius = 30;
        
        public RunnerCircle(RunningDriver RD) {
            
            runningDriver = RD;
            if(DEBUG)Log.i(tag,
              "RunnerCircle( )"+"\n"+
              "screenWidth="+screenWidth+"\n"+
              "screenHeighth="+screenHeight+"\n"+
              "");

            cx = (int)Math.round(Math.random( )*screenWidth);
            cy = (int)Math.round(Math.random( )*screenHeight);
            if(DEBUG)Log.i(tag,
              "cx="+cx+"\n"+
              "cy="+cy+"\n"+
              "");
                 
            dx = (int)Math.signum(Math.round(Math.random( ))-.5)*10;
            dy = (int)Math.signum(Math.round(Math.random( ))-.5)*10;
            if(DEBUG)Log.i(tag,
              "dx="+dx+"\n"+
              "dy="+dy+"\n"+
              "");
                 
            int c = cPalette[(int)Math.round(Math.random( )*(cPalette.length-1))];
            paint.setStyle(Style.FILL);
            paint.setColor(c);
            if(DEBUG)Log.i(tag,
              "paint.set"+"\n"+
              "");

        }

        @Override
        public void run( ) {
            synchronized(runningDriver) { 
                runningDriver.canvas.drawCircle(
                  cx, cy, radius,paint);
                if( ! ThroughSW )  { 
                    if( (cx+dx)<0 | screenWidth<(cx+dx) ){
                        dx = -dx;
                    }
                    cx += dx;
                    if( (cy+dy)<0 | screenHeight<(cy+dy) ){
                        dy = -dy;
                    }
                    cy += dy;
                }
            }
        }
    }

    public class RunningDriver implements 
        Runnable {
       
        RunnerFigure[] runnerMembers = new RunnerFigure[5];
// ↑ 手抜きで配列にしているが、本来ならノードで連結させるのが筋。
        public Canvas canvas;
        public SurfaceHolder surfaceHolder;
// ↑ 本来なら これら「canvas、surfaceHolder」は ここで記述するべきではなく、
// 別クラスを継承しで そこで記述してやるのが筋。
        
        int runnerNumber;
        public Thread runningEngine = null;
        public boolean runningEngineSW = false; // true; // 
        public boolean waitSW = false; // true; // 
        long interval = 50;
        
        public RunningDriver( ){ }
        
        public void launch(int LaunchMode){
            switch (LaunchMode){
                case LAUNCH_CREATE:
                    initialize( );
                    runningEngineCreate( );
                break;    
                
                case LAUNCH_RESTART:
                    runningEngineCreate( );
                break;
                
                default:
            }
        }
        
        public void initialize( ){
// ↑ 本来なら この「initialize( )」メソッドは
// この"RunningDriver"クラスでは抽象メソッドとし、
// 別クラスで それらのメソッドをオーバーライドしてやるのが筋。

            for( int i = 0; i<runnerMembers.length; i++){
                runnerMembers[i] = new RunnerCircle(this);
            }
            // runningEngineCreate( );
        }
      
        public void runnerAcceptAll( ){
           for( int i = 0; i<runnerMembers.length; i++){
               if( runnerMembers[i]!=null ){
                   runnerMembers[i].ThroughSW = false; // true; // 
               }
           }
        }
      
        public void runnerThroughAll( ){
            for( int i = 0; i<runnerMembers.length; i++){
                if( runnerMembers[i]!=null ){
                    runnerMembers[i].ThroughSW = true; // false; // 
                }
            }
        }
        
        public void runningEngineCreate( ) {
            runnerAcceptAll( );
            runningEngineSW = true; // false; // 
            waitSW = false; // true; // 
            // runningEngine = null;
            runningEngine = new Thread(this);
            runningEngine.start( );
        }
        
        public void runningEngineDestroy( ){
            try{
                runningEngine.interrupt( );
            } catch(NullPointerException e) {
                // e.printStackTrace( );
                if(DEBUG)Log.i(tag, "RunningDriver:runningEngineDestroy( ):NullPointerException;");
            }
        }
        
        public synchronized void runningHeader( ){
// ↑ Method に直に指定した場合は「synchronized(this)」と等価になるらしい。
            Paint bgPaint = new Paint();
            bgPaint.setStyle(Style.FILL);
            bgPaint.setColor(Color.WHITE);
            canvas = surfaceHolder.lockCanvas( );
            canvas.drawRect(
              0, 0, screenWidth, screenHeight,
              bgPaint);
        }
        
        public synchronized void runningFooter( ){
// ↑ Method に直に指定した場合は「synchronized(this)」と等価になるらしい。
            surfaceHolder.unlockCanvasAndPost(canvas);
        }
        
        public void run( ){
            if(DEBUG)Log.i(tag, "RunningDriver.run( );");
            while(
              runningEngine!=null &               
              runningEngineSW
            ){
                synchronized(this) { 
// ↑ この this は runningEngine では無く RunningDriver のインスタンス。
                    try{
                    
// 本来なら下記「runningHeader( )、runningFooter( )」メソッドは
// この"RunningDriver"クラスでは抽象メソッドとし、
// 別クラスで それらのメソッドをオーバーライドしてやるのが筋。
                        runningHeader( );
                        for( runnerNumber = 0; runnerNumber<runnerMembers.length; runnerNumber++){
                           if( runnerMembers[runnerNumber]!=null ){
                               runnerMembers[runnerNumber].run( );
                           }
                       }
                       runningFooter( );
                    } catch(NullPointerException e) {
                        // e.printStackTrace( );
                        if(DEBUG)Log.i(tag, "RunningDriver:run( ):NullPointerException;");
                        runningEngineSW = false; // true; //
                    }
                    
                    while(waitSW){
                        try{
                            this.wait( );
// ↑ この this は runningEngine では無く RunningDriver のインスタンス。
                        }catch(InterruptedException e){
                            // e.printStackTrace( ); 
                            if(DEBUG)Log.i(tag, "RunningDriver:run( ):InterruptedException;");
                            runningEngineSW = false; // true; //
                        }
                    }
                    
                    if( runningEngineSW ){
                        try{
                            Thread.sleep(interval);
// ↑ 「sleep(interval)」は指定された時間以上に待たされる場合があるようなので、
// 1回のループは「プログラムの処理時間+sleep(interval+α)」 となるから、
// 正確(完璧に正確無比と言う意味ではない)なタイマーを作りたい場合は
//「long time = System.currentTimeMillis( )」を使って一工夫が必要となる。                    
                        } catch(InterruptedException e) {
                            // e.printStackTrace( ); 
                            if(DEBUG)Log.i(tag, "RunningDriver:run( ):InterruptedException;");
                            runningEngineSW = false; // true; //
                        }
                    }
                    
                }
            }
            runningEngine = null;
        }
    }
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        if(DEBUG)Log.i(tag, "onCreate( );");
        app = this;
        appLaunchMode = LAUNCH_CREATE;
         
        cetMessage = (EditText)findViewById(R.id.cet_message);
        vsMessage = vsMessage+"onCreate\n";
        cetMessage.setText(vsMessage, BufferType.NORMAL);
        
        runningDriver = new RunningDriver( );
// 「MainActivity」クラスの この「onCreate( )」コンストラクターでは
// まだ"SurfaceView"の生成が完了してない場合が有るようで、
// その時点で"Thread"が実行された場合
// 「surfaceHolder.lockCanvas( )」による"Canvas"の生成が"null"になってしまうので、
// 「RunningDriver( )」コンストラクターには
// 「runningEngineCreate( )」("Thread"の生成・実行)は内包しない。
// 又、「RunnerCircle( )」 コンストラクター実行時には
// 「screenWidth、screenHeight」が設定されていなければならないので
// 「RunningDriver( )」コンストラクターには内包せず、別途「initialize( )」に内包する。
// それら「initialize( )、runningEngineCreate( )」は「launch( )」に内包し「surfaceChanged( )」で実行する。
// ただし「launch( )」に内包された それら(「initialize( )、runningEngineCreate( )」)は"appLaunchMode"で実行の可否が決定される。
        
        if(DEBUG)Log.i(tag, "runningDriver = new RunningDriver( );");
        vsMessage = vsMessage+"runningDriver = new RunningDriver( )\n";
        cetMessage.setText(vsMessage, BufferType.NORMAL);
        
        /* ボタンを取り出す */
        Button cbAcceptAll = (Button)findViewById(R.id.cb_accept_all);
        /* ボタンにリスナーを登録する */
        cbAcceptAll.setOnClickListener(new OnClickListener( ) {
            @Override
            public void onClick(View v) {
                runningDriver.runnerAcceptAll( );
            }
        });    
        
        /* ボタンを取り出す */
        Button cbThroughAll = (Button)findViewById(R.id.cb_through_all);
        /* ボタンにリスナーを登録する */
        cbThroughAll.setOnClickListener(new OnClickListener( ) {
            @Override
            public void onClick(View v) {
                runningDriver.runnerThroughAll( );
            }
        });

        /* ボタンを取り出す */
        Button cbWait = (Button)findViewById(R.id.cb_wait);
        /* ボタンにリスナーを登録する */
        cbWait.setOnClickListener(new OnClickListener( ) {
            @Override
            public void onClick(View v) {
                runningDriver.waitSW = true; // false; // 
            }
        });  
        
        /* ボタンを取り出す */
        Button cbNotify = (Button)findViewById(R.id.cb_notify);
        /* ボタンにリスナーを登録する */
        cbNotify.setOnClickListener(new OnClickListener( ) {
            @Override
            public void onClick(View v) {
                try{
                    synchronized(runningDriver){
                        runningDriver.waitSW = false; // true; //     
                        runningDriver.notify( );
                    }
                }catch(IllegalMonitorStateException  e){ }
            }
        });  
        
        /* ボタンを取り出す */
        Button cbCreate = (Button)findViewById(R.id.cb_create);
        /* ボタンにリスナーを登録する */
        cbCreate.setOnClickListener(new OnClickListener( ) {
            @Override
            public void onClick(View v) {
                runningDriver.runningEngineCreate( );
            }
        });    
        
        /* ボタンを取り出す */
        Button cbDestroy = (Button)findViewById(R.id.cb_destroy);
        /* ボタンにリスナーを登録する */
        cbDestroy.setOnClickListener(new OnClickListener( ) {
            @Override
            public void onClick(View v) {
                runningDriver.runningEngineDestroy( );
            }
        });  

    }
    
    @Override
    protected void onRestart( ) {
        super.onRestart( );
        if(DEBUG)Log.i(tag, "onRestart( );");
        
        appLaunchMode = LAUNCH_RESTART;
    }
    
    @Override
    protected void onStart( ) {
        super.onStart( );
        if(DEBUG)Log.i(tag, "onStart( );");
        
        surfaceChangedSW = false; // true; //
        SurfaceView SV = (SurfaceView)findViewById(R.id.SV);
        SurfaceHolder SH = SV.getHolder();
        SH.addCallback(app);   
        // SV.setFocusable(true);
        // SV.requestFocus( );
        runningDriver.surfaceHolder = SH;
    }
    
    @Override
    protected void onResume( ) {
        super.onResume( );
        if(DEBUG)Log.i(tag, "onResume( );");
    }
    
    @Override
    protected void onPause( ) {
        super.onPause( );
        if(DEBUG)Log.i(tag, "onPause( );");
    }

    @Override
    protected void onStop( ) {
        super.onStop( );
        if(DEBUG)Log.i(tag, "onStop( );");
        
        runningDriver.runningEngineDestroy( );
        runningDriver.surfaceHolder.removeCallback(app);
    }
    
    @Override
    protected void onDestroy( ) {
        super.onDestroy( );
        if(DEBUG)Log.i(tag, "onDestroy( );");
    }
    
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) { }

    @Override
    public void surfaceChanged(SurfaceHolder holder, 
     int format, int width, int height) {

       screenWidth = width;
       screenHeight = height;
       
       if(DEBUG)Log.i(tag,
         "surfaceChanged( );"+"\n"+
         "screenWidth="+screenWidth+"\n"+
         "screenHeighth="+screenHeight+"\n"+
         "");
       vsMessage = vsMessage+
         "screenWidth="+screenWidth+"\n"+
         "screenHeighth="+screenHeight+"\n"+
         "";
       cetMessage.setText(vsMessage, BufferType.NORMAL);
                 
        vsMessage = vsMessage+"surfaceChanged( )\n";
        cetMessage.setText(vsMessage, BufferType.NORMAL);
       
       if( ! surfaceChangedSW ){
           surfaceChangedSW = true; // false; //
// "surfaceChangedSW"がクリアーされない限りは、「surfaceChanged( )」 が2回以上呼ばれても、ここは1回しか実行されない。
           
           runningDriver.launch(appLaunchMode);
       }
     
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) { }
    
}


『res\layout\activity_main.xml』


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <SurfaceView
        android:id="@+id/SV"
        android:layout_width="match_parent"
        android:layout_height="200dp" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <Button
            android:id="@+id/cb_accept_all"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/AcceptAll" />

        <Button
            android:id="@+id/cb_through_all"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/ThroughAll" />
        
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <Button
            android:id="@+id/cb_notify"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/Notify" />

        <Button
            android:id="@+id/cb_wait"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/Wait" />

    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <Button
            android:id="@+id/cb_create"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/Create" />

        <Button
            android:id="@+id/cb_destroy"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/Destroy" />

    </LinearLayout>

    <EditText
        android:id="@+id/cet_message"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:inputType="textMultiLine" >

        <requestFocus />
    </EditText>

</LinearLayout>


『res\values\strings.xml』


<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string name="app_name">A009_JFX</string>
    <string name="action_settings">Settings</string>
    <string name="AcceptAll">Accept</string>
    <string name="ThroughAll">Through</string>
    <string name="Notify">Notify</string>
    <string name="Wait">Wait</string>
    <string name="Create">Create</string>
    <string name="Destroy">Destroy</string>
    
</resources>


<?xml version="1.0" encoding="utf-8"?>
<manifest
    xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.a009_pkg"
    android:versionName="1.0"
    android:versionCode="7" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="20" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name"
            android:launchMode="singleInstance" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>


<Number>: [0000087A]  <Date>: 2014/11/22 00:13:40
<Title>: Android 用 JavaFX プログラミング "Widget"編で参考にしたサイト
<Name>: amanojaku@管理人



今回、Android 用 JavaFX プログラミング "Widget"編で参考にしたサイト。

"Widget"と言うと、一般的には"Widget"アプリケーションが連想されるが、実は("Button"や"TextView"などの)非"Layout"系「UI(User Interface) Component」も"Widget"と呼ばれている。
もしかしてアイコンの代わりに画面に「"Widget" UI(User Interface) Component」を配置できるアプリだから"Widget"アプリケーションと呼ばれるのかもしれない。


アプリウィジェットについて - Android Memo Wiki
http://nbrt.sakura.ne.jp/zino/w/index.php?title=%E3%82%A2%E3%83%97%E3%83%AA%E3%82%A6%E3%82%A3%E3%82%B8%E3%82%A7%E3%83%83%E3%83%88%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6

Androidで動く携帯Javaアプリ作成入門(10):Androidのホーム画面に常駐するアプリを作るには - @IT
http://www.atmarkit.co.jp/ait/articles/0909/28/news085.html
http://www.atmarkit.co.jp/ait/articles/0909/28/news085_2.html
http://www.atmarkit.co.jp/ait/articles/0909/28/news085_3.html

AppWidgetからアクティビティを起動する - Androidプログラマへの道 〜 Moonlight 明日香 〜
http://seesaawiki.jp/w/moonlight_aska/d/AppWidget%A4%AB%A4%E9%A5%A2%A5%AF%A5%C6%A5%A3%A5%D3%A5%C6%A5%A3%A4%F2%B5%AF%C6%B0%A4%B9%A4%EB


<Number>: [0000087B]  <Date>: 2014/12/27 12:19:32
<Title>: Widget での Click Event
<Name>: amanojaku@管理人



Widget での Click Event

とりあえずアプリケーション名は"W0063_JFX"、プロジェクト名は"W0063_Prj"、パッケージ名は"com.android.appwidget.w0063_pkg"としている、「Create Activity」は OFF にして、その他はデフォルトでスケルトンを作成。
"src"フォルダーをマウスの右・クリックでショートカット・メニューから[New]→[Package]で"com.android.appwidget.w0063_pkg"(Package)を作成。
「src/com.android.appwidget.w0063_pkg」Package フォルダーをマウスの右・クリックでショートカット・メニューから[New]→[File]で[File Name]:"MainWidget.java"(Java File)を作成(この場合、ファイル拡張子まで入力)。
「res/layout」フォルダーをマウスの右・クリックでショートカット・メニューから[New]→[Android XML File]で[Resources Type]:[Layout]とし[File]:"widget_main"(XML File)を作成。
「res」フォルダーをマウスの右・クリックでショートカット・メニューから[New]→[Folder]で[Folder Name]:"xml"(Folder)を作成。
「res/xml」フォルダーをマウスの右・クリックでショートカット・メニューから[New]→[File]で[File Name]:"widget_info.xml"(XML File)を作成(この場合、ファイル拡張子まで入力)。


『src/com.android.appwidget.w0063_pkg/MainWidget.java』


package com.android.appwidget.w0063_pkg;

import java.util.Date;
import android.app.PendingIntent;
import android.app.Service;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.widget.RemoteViews;

/** クリックを使用するサンプル。 */
public class MainWidget extends AppWidgetProvider {
    
    private static final String ACTION_MY_CLICK = "com.android.appwidget.w0063_pkg.IntentFilter.ACTION_MY_CLICK";

    static long ilCounter;
    
    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_main);
        remoteViews.setTextViewText(R.id.ctvDate, "onUpdate");
        remoteViews.setTextViewText(R.id.ctvCounter, "Clic:"+ilCounter);
        
        // ウィジェットの更新
        appWidgetManager.updateAppWidget(appWidgetIds, remoteViews);
        
        Intent serviceIntent = new Intent(context, MyService.class);
        context.startService(serviceIntent);
    }
    
    public static class MyService extends Service {
        @SuppressWarnings("deprecation")
        @Override
        public void onStart(Intent intent, int startId) {
            ComponentName thisWidget = new ComponentName(this, MainWidget.class);
            AppWidgetManager manager = AppWidgetManager.getInstance(this);
            
            RemoteViews remoteViews = new RemoteViews(getPackageName(), R.layout.widget_main);
            if(ACTION_MY_CLICK.equals(intent.getAction( ))) {
                remoteViews.setTextViewText(R.id.ctvDate, new Date().toLocaleString( ));
                ilCounter++;
                remoteViews.setTextViewText(R.id.ctvCounter, "Clic:"+ilCounter);
            }
            
            Intent clickIntent = new Intent();
            clickIntent.setAction(ACTION_MY_CLICK);
            PendingIntent pendingIntent = PendingIntent.getService(this, 0, clickIntent, 0);
            
            remoteViews.setOnClickPendingIntent(R.id.ctvDate, pendingIntent);
            remoteViews.setOnClickPendingIntent(R.id.button1, pendingIntent);
            
            manager.updateAppWidget(thisWidget, remoteViews);
        }

        @Override
        public IBinder onBind(Intent intent) {
            return null;
        }
    }
}


『res/layout/widget_main.xml』


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

    <TextView
        android:id="@+id/ctvDate"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:background="#333333"
        android:gravity="center"
        android:text="Date"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:textColor="#ffffff" />

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" >

        <TextView
            android:id="@+id/ctvCounter"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:background="#333333"
            android:text="ClicCounter"
            android:textAppearance="?android:attr/textAppearanceMedium" />

        <Button
            android:id="@+id/button1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:text="Please click!" />
    </LinearLayout>

</LinearLayout>


『res/xml/widget_info.xml』


<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:minWidth="300dip"
    android:minHeight="70dip"
    android:updatePeriodMillis="0"
    android:initialLayout="@layout/widget_main" />


『AndroidManifest.xml』


<?xml version="1.0" encoding="utf-8"?>
<manifest
    xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.android.appwidget.w0063_pkg"
    android:versionName="1.0" 
    android:versionCode="10" >
    
    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="12" />   
<!-- ↑ targetSdkVersion が 14以上だと Widget のサイズの計算法が変わるそうで、  -->        
<!-- 古い  Version と互換性を持たせたい場合は targetSdkVersion を 13以下にすれば良いらしい。 -->        
<!-- (「API Level 13」以下とするなら)当方は「API Level 12」(Android OS 3.1)までしか  --> 
<!-- インストールしてないので targetSdkVersion は 12 とする(警告が出るが放置で良い)。  -->        
    
    <application
         android:allowBackup="true"
         android:label="@string/app_name"
         android:icon="@drawable/ic_launcher" >
       <receiver
            android:label="@string/app_name"
            android:name=".MainWidget" >
            <intent-filter>
                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
            </intent-filter>
            <meta-data
                android:name="android.appwidget.provider"
                android:resource="@xml/widget_info" />
        </receiver>
        <service android:name=".MainWidget$MyService">
            <intent-filter>
                <action android:name="com.android.appwidget.w0063_pkg.IntentFilter.ACTION_MY_CLICK" />
            </intent-filter>
        </service>
    </application>
</manifest>


<Number>: [0000087E]  <Date>: 2014/12/27 12:21:26
<Title>: Widget から Activity を起動
<Name>: amanojaku@管理人



Widget から Activity を起動

とりあえずアプリケーション名は"W0121_JFX"、プロジェクト名は"W0121_Prj"、パッケージ名は"com.moonlight_aska.android.w0121_pkg"、「Create Activity」は ON 、"Activity"名は"MainActivity"、"Layout"名は"activity_main"としている、その他はデフォルトでスケルトンを作成。
「src/com.android.appwidget.w0121_pkg」Package フォルダーをマウスの右・クリックでショートカット・メニューから[New]→[File]で[File Name]:"MainWidget.java"(Java File)を作成(この場合、ファイル拡張子まで入力)。
「res/layout」フォルダーをマウスの右・クリックでショートカット・メニューから[New]→[Android XML File]で[Resources Type]:[Layout]とし[File]:"widget_main"(XML File)を作成。
「res」フォルダーをマウスの右・クリックでショートカット・メニューから[New]→[Folder]で[Folder Name]:"xml"(Folder)を作成。
「res/xml」フォルダーをマウスの右・クリックでショートカット・メニューから[New]→[File]で[File Name]:"widget_info.xml"(XML File)を作成(この場合、ファイル拡張子まで入力)。
なお、Activity のボタンはダミー。


『src/com.moonlight_aska.android.w0121_pkg/MainActivity.java』


package com.moonlight_aska.android.w0121_pkg;

import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;

public class MainActivity extends ActionBarActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
}


『src/com.moonlight_aska.android.w0121_pkg/MainWidget.java』


package com.moonlight_aska.android.w0121_pkg;

import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.widget.RemoteViews;

public class MainWidget extends AppWidgetProvider {
    
    static final String tag = "Log.Debug"; // フィルタリング用タグ
    static final boolean DEBUG = true; // false; // 
// ↑ この"DEBUG"は予約語では無い、"Java"において"final"(定数)の場合は
// 全部 大文字で記述するの事が推奨されているようだ。
// 「DEBUG=true」に設定すれば「if(DEBUG)Log.i(〜)」によって"LogCat"に出力される。
    
    @Override
    public void onEnabled(Context context) {
        if(DEBUG)Log.i(tag, "W0121/MainWidget.onEnabled( );");
    }
    
    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager,
        int[] appWidgetIds) {
        // TODO Auto-generated method stub
        super.onUpdate(context, appWidgetManager, appWidgetIds);
        if(DEBUG)Log.i(tag, "W0121/MainWidget.onUpdate( );");
        // アクティビティの指定
        Intent intent = new Intent(context, MainActivity.class);
        // PendingIntentの取得
        PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
        RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_main);
        // インテントによるアクティビティ起動
        remoteViews.setOnClickPendingIntent(R.id.btnGoActivity, pendingIntent);
        appWidgetManager.updateAppWidget(appWidgetIds, remoteViews);
    }
}


『res/layout/activity_main.xml』


<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.moonlight_aska.android.w0121_pkg.MainActivity" >

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!" />

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!" />

</LinearLayout>


『res/layout/widget_main.xml』


<?xml version="1.0" encoding="utf-8"?>
<Button
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/btnGoActivity"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:text="Go Activity" />


『res/xml/widget_info.xml』


<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:updatePeriodMillis="0"
    android:minHeight="48dip"
    android:minWidth="100dip"
    android:initialLayout="@layout/widget_main" />


『AndroidManifest.xml』
※この場合 <activity>タグに"launchMode"は設定できないようだ、この場合 「launchMode="singleInstance"」を設定しなくても Activity のインスタンスは1つだけに限定されるようだ。


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.moonlight_aska.android.w0121_pkg"
    android:versionName="1.0"
    android:versionCode="17" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="12" />
<!-- ↑ targetSdkVersion が 14以上だと Widget のサイズの計算法が変わるそうで、  -->        
<!-- 古い  Version と互換性を持たせたい場合は targetSdkVersion を 13以下にすれば良いらしい。 -->        
<!-- (「API Level 13」以下とするなら)当方は「API Level 12」(Android OS 3.1)までしか  --> 
<!-- インストールしてないので targetSdkVersion は 12 とする(警告が出るが放置で良い)。  -->        

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <receiver
            android:name=".MainWidget"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
            </intent-filter>
            <meta-data
                android:name="android.appwidget.provider"
                android:resource="@xml/widget_info" />
        </receiver>
        <!-- アクティビティの登録 -->
        <activity
            android:name=".MainActivity" >
        </activity>
    </application>

</manifest>


<Number>: [000008AA]  <Date>: 2014/12/27 14:55:44
<Title>: Alarm (1)
<Name>: amanojaku@管理人



Alarm (1)

今回、Android 用 JavaFX プログラミングで参考にしたサイト。
http://android.keicode.com/basics/services-schedule-with-alarmmanager.php

とりあえずアプリケーション名は"Alarm0017_JFX"、プロジェクト名は"Alarm0017_Prj"、パッケージ名は"com.keicode.android.alarm0017_pkg"、"Activity"名は"AlarmActivity"、"Layout"名は"activity_main"としている、その他はデフォルトでスケルトンを作成。
「res\menu」フォルダー内のファイル名が"main.xml"になっていなかったら、そのファイルをマウスの右・クリックでショートカット・メニューから[Refactor]→[Rename]でファイル名を"main.xml"に変更。

なお、基本的に(Alarm スレッドのような)メインのスレッドとは別のスレッドから「GUI:Graphical User Interface」(=Java で言う所の UI Control:User Interface Control)を操作できないようだ。
Handler を使えば何とかなるらしいが、ここでは Handler は使わずに、Log 出力とする。


『src/com.keicode.android.alarm0017_pkg/AlarmActivity.java』


package com.keicode.android.alarm0017_pkg;

import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.os.Bundle;
import android.os.Handler;
import android.view.Menu;
import android.view.MenuItem;
import android.app.AlarmManager;
import android.app.IntentService;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class AlarmActivity extends ActionBarActivity {

    static final String tag = "Log.Debug"; // フィルタリング用タグ
    static final boolean DEBUG = true; // false; // 
//↑ この"DEBUG"は予約語では無い、"Java"において"final"(定数)の場合は
//全部 大文字で記述するの事が推奨されているようだ。
//「DEBUG=true」に設定すれば「if(DEBUG)Log.i(〜)」によって"LogCat"に出力される事になる。

    Button cbSchedule;
    Button cbCancel;
    long interval = 3000;
    
    public static class MyService extends IntentService {

        static final String serviceName = MyService.class.getSimpleName( );
        // getName( ) // パッケージ名を含むクラス名
        // getSimpleName( ) // クラス名のみ
        
        public MyService( ) {
            super(serviceName);
            if(DEBUG)Log.i(tag, serviceName);
        }

        @Override
        protected void onHandleIntent(Intent intent) {
            if(DEBUG)Log.i(tag, "onHandleIntent( );");
        }
        
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if(DEBUG)Log.i(tag, "onCreate( );");
        setContentView(R.layout.activity_main);
        
        cbSchedule = (Button)findViewById(R.id.cb_schedule);
        cbSchedule.setOnClickListener(new OnClickListener(){
            @Override
            public void onClick(View v) {
              scheduleService( );
            }
        });
        
        cbCancel = (Button)findViewById(R.id.cb_cancel);
        cbCancel.setOnClickListener(new OnClickListener(){
            @Override
            public void onClick(View v) {
              cancelService( );
            }
        });
    }
    
    @Override
    protected void onPause( ) {
        super.onPause( );
    }
    
    @Override
    protected void onStop( ) {
        super.onStop( );
        
        cancelService( );
// ↑ Activity が Stop したら「Alarm Service」を停止している。
    }
    
    @Override
    protected void onDestroy( ) {
        super.onDestroy( );
    }
    
    protected void scheduleService( ){
        if(DEBUG)Log.i(tag, "scheduleService( );");
        Context context = getBaseContext( );
        Intent intent = new Intent(context, MyService.class);
        PendingIntent pendingIntent 
          = PendingIntent.getService(
            context, -1, intent, 
            PendingIntent.FLAG_UPDATE_CURRENT);
        AlarmManager alarmManager 
          = (AlarmManager)context.getSystemService(ALARM_SERVICE);
        alarmManager.setInexactRepeating(
          AlarmManager.RTC, 
          System.currentTimeMillis( ),
          interval, pendingIntent);
    }
    
    protected void cancelService( ){
        if(DEBUG)Log.i(tag, "cancelService( );");
        Context context = getBaseContext( );
        Intent intent = new Intent(context, MyService.class);
        PendingIntent pendingIntent 
          = PendingIntent.getService(
            context, -1, intent, 
            PendingIntent.FLAG_UPDATE_CURRENT);
        AlarmManager alarmManager 
          = (AlarmManager)
          context.getSystemService(ALARM_SERVICE);
        alarmManager.cancel(pendingIntent);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater( ).inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId( );
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
}


『res\layout\activity_main.xml』


<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.keicode.android.alarm0017_pkg.AlarmActivity" >

    <TextView
        android:id="@+id/ctv_counter"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="AlarmManager" />

    <Button
        android:id="@+id/cb_schedule"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="schedule" />

    <Button
        android:id="@+id/cb_cancel"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="cancel" />

</LinearLayout >


『AndroidManifest.xml』


<?xml version="1.0" encoding="utf-8"?>
<manifest
    xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.keicode.android.alarm0017_pkg"
    android:versionName="1.0"
    android:versionCode="9" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="20" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".AlarmActivity"
            android:label="@string/app_name"
            android:launchMode="singleInstance" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <service android:name=".AlarmActivity$MyService"></service>
    </application>

</manifest>


<Number>: [000008AD]  <Date>: 2014/12/27 14:59:59
<Title>: Alarm (1) 改
<Name>: amanojaku@管理人



Alarm (1) 改

とりあえずアプリケーション名は"Alarm0018_JFX"、プロジェクト名は"Alarm0018_Prj"、パッケージ名は"com.keicode.android.alarm0018_pkg"、"Activity"名は"AlarmActivity"、"Layout"名は"activity_main"としている、その他はデフォルトでスケルトンを作成。
「res\menu」フォルダー内のファイル名が"main.xml"になっていなかったら、そのファイルをマウスの右・クリックでショートカット・メニューから[Refactor]→[Rename]でファイル名を"main.xml"に変更。

基本的に(Alarm スレッドのような)メインのスレッドとは別のスレッドから「GUI:Graphical User Interface」(=Java で言う所の UI Control:User Interface Control)を操作できないようなので、Handler を使って「GUI:Graphical User Interface」(=Java で言う所の UI Control:User Interface Control)を操作する。


『src/com.keicode.android.alarm0018_pkg/AlarmActivity.java』


package com.keicode.android.alarm0018_pkg;

import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.Menu;
import android.view.MenuItem;
import android.annotation.SuppressLint;
import android.app.AlarmManager;
import android.app.IntentService;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class AlarmActivity extends ActionBarActivity {

    static final String tag = "Log.Debug"; // フィルタリング用タグ
    static final boolean DEBUG = true; // false; // 
//↑ この"DEBUG"は予約語では無い、"Java"において"final"(定数)の場合は
//全部 大文字で記述するの事が推奨されているようだ。
//「DEBUG=true」に設定すれば「if(DEBUG)Log.i(〜)」によって"LogCat"に出力される事になる。

    TextView ctvCounter;
    Button cbSchedule;
    Button cbCancel;
    long interval = 1000;
    static Handler hdrCFlash;
    static long ilCounter;
    
    public static class MyService extends IntentService {

        static final String serviceName = MyService.class.getSimpleName( );
        // getName(); // パッケージ名を含むクラス名
        // getSimpleName() // クラス名のみ
        
        public MyService( ) {
            super(serviceName);
            if(DEBUG)Log.i(tag, serviceName);
        }

        @Override
        protected void onHandleIntent(Intent intent) {
            if(DEBUG)Log.i(tag, "onHandleIntent( );");
            ilCounter++;
            hdrCFlash.sendEmptyMessage(0);
        }
        
    }
    
    @Override @SuppressLint("HandlerLeak") 
    protected void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        if(DEBUG)Log.i(tag, "onCreate( );");
        setContentView(R.layout.activity_main);
        
        ctvCounter = (TextView)findViewById(R.id.ctv_counter);
        
        hdrCFlash = new Handler( ){
            public void handleMessage(Message msg){
                ctvCounter.setText("Counter:"+ilCounter);
            }
        };
        
        cbSchedule = (Button)findViewById(R.id.cb_schedule);
        cbSchedule.setOnClickListener(new OnClickListener( ){
            @Override
            public void onClick(View v){
                scheduleService( );
            }
        });
        
        cbCancel = (Button)findViewById(R.id.cb_cancel);
        cbCancel.setOnClickListener(new OnClickListener( ){
            @Override
            public void onClick(View v){
                cancelService( );
            }
        });
        
    }
    
    @Override
    protected void onPause( ) {
        super.onPause( );
    }
    
    @Override
    protected void onStop( ) {
        super.onStop( );
        
        cancelService( );
// ↑ Activity が Stop したら「Alarm Service」を停止している。
    }
    
    @Override
    protected void onDestroy( ) {
        super.onDestroy( );
    }
    
    protected void scheduleService( ){
        if(DEBUG)Log.i(tag, "scheduleService( );");
        Context context = getBaseContext( );
        Intent intent = new Intent(context, MyService.class);
        PendingIntent pendingIntent 
          = PendingIntent.getService(
            context, -1, intent, 
            PendingIntent.FLAG_UPDATE_CURRENT);
        AlarmManager alarmManager 
          = (AlarmManager)context.getSystemService(ALARM_SERVICE);
        alarmManager.setInexactRepeating(
          AlarmManager.RTC, 
          System.currentTimeMillis( ),
          interval, pendingIntent);
    }
    
    protected void cancelService( ){
        if(DEBUG)Log.i(tag, "cancelService( );");
        ilCounter = 0;
        Context context = getBaseContext( );
        Intent intent = new Intent(context, MyService.class);
        PendingIntent pendingIntent 
          = PendingIntent.getService(
            context, -1, intent, 
            PendingIntent.FLAG_UPDATE_CURRENT);
        AlarmManager alarmManager 
          = (AlarmManager)
          context.getSystemService(ALARM_SERVICE);
        alarmManager.cancel(pendingIntent);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu){
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater( ).inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item){
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId( );
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
}


『res\layout\activity_main.xml』


<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.keicode.android.alarm0018_pkg.AlarmActivity" >

    <TextView
        android:id="@+id/ctv_counter"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="AlarmManager" />

    <Button
        android:id="@+id/cb_schedule"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="schedule" />

    <Button
        android:id="@+id/cb_cancel"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="cancel" />

</LinearLayout >


『AndroidManifest.xml』


<?xml version="1.0" encoding="utf-8"?>
<manifest
    xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.keicode.android.alarm0018_pkg"
    android:versionName="1.0"
    android:versionCode="10" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="20" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".AlarmActivity"
            android:label="@string/app_name"
            android:launchMode="singleInstance" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <service android:name=".AlarmActivity$MyService"></service>
    </application>

</manifest>


<Number>: [000008B2]  <Date>: 2014/12/26 02:57:48
<Title>: Alarm (3)
<Name>: amanojaku@管理人



Alarm (3)

今回、Android 用 JavaFX プログラミングで参考にしたサイト。
http://techbooster.jpn.org/andriod/multimedia/3417/

キッチン・タイマー:指定された秒数をカウント・ダウンし、ゼロになったらシステム音を鳴らす。
とりあえずアプリケーション名は"Alarm0019_JFX"、プロジェクト名は"Alarm0019_Prj"、パッケージ名は"com.example.alarm0019_pkg"、"Activity"名は"MainActivity"、"Layout"名は"activity_main"としている、その他はデフォルトでスケルトンを作成。



『src/com.example.alarm0019_pkg/MainActivity.java』


package com.example.alarm0019_pkg;

import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.media.AudioManager;
import android.media.ToneGenerator;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.Menu;
import android.view.MenuItem;
import android.annotation.SuppressLint;
import android.app.AlarmManager;
import android.app.IntentService;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class MainActivity extends ActionBarActivity {

    static final String tag = "Log.Debug"; // フィルタリング用タグ
    static final boolean DEBUG = true; // false; // 
//↑ この"DEBUG"は予約語では無い、"Java"において"final"(定数)の場合は
//全部 大文字で記述するの事が推奨されているようだ。
//「DEBUG=true」に設定すれば「if(DEBUG)Log.i(〜)」によって"LogCat"に出力される事になる。

    static MainActivity app;
    static Handler hdrCFlash;
    static volatile long ilCounter; // volatile:最適化の抑制。
// ↑ "volatile"(最適化の抑制)により「Event、他の Thread」からの変数の可視性が保障されます。
// ただ"volatile"(最適化の抑制)で「Event、他の Thread」からの変数の正しい操作が保障されるわけではないので、過信するのは禁物です。
// 例えば「volatile int i」と宣言されていたとして「i++」と言う単純な命令が「メモリーからレジスターに読み取り、レジスターに1を加算、レジスターからメモリーに書き出し」と言う3個の命令として実行されるので、そこに"Atomic"性はありません。
// つまり 一見 単純に見える命令でも取りあえずは"Atomic"性は保障されないと考えておくベキ。
// "Atomic"性を確保したい場合は"synchronized"を使用する必要があります。
    
    EditText cetCounter;
    Button cbStart;
    Button cbCancel;
    long interval = 1000;
  
    public static class MyService extends IntentService {

        static final String serviceName = MyService.class.getSimpleName( );
        // getName(); // パッケージ名を含むクラス名
        // getSimpleName() // クラス名のみ
        
        public MyService( ) {
            super(serviceName);
            if(DEBUG)Log.i(tag, serviceName);
        }

        @Override
        protected void onHandleIntent(Intent intent) {
            if(DEBUG)Log.i(tag, "onHandleIntent( );");
            synchronized(app) {
// ↑ この synchronized によって「ilCounter--」、「if(ilCounter<=0)」、「app.cancelService( )」内の「ilCounter = 0」と それに関連する Process 、「if(ilCounter<=0)」などの一連の Process の"Atomic"性を確保している。
// 恐らく変数にアクセスされる側(この場合は app)を Monitor にすれば良いと思われる、Method に直に指定した場合は「synchronized(this)」と等価になるらしい。
// こんな簡単な Program で わざわざ synchronized を使う事も無いのだけど、
// 少し 複雑になって来ると必要になる事もあるので、その場合のサンプル的な意味合い。
                ilCounter--;
                if(ilCounter<=0){
                    app.cancelService( );
                }
                hdrCFlash.sendEmptyMessage(0);
                if(ilCounter<=0) beep( );
            }
        }
        
    }
  
    static public void beep( ){
        ToneGenerator tg
          = new ToneGenerator(AudioManager.STREAM_SYSTEM, ToneGenerator.MAX_VOLUME);
        for(int i = 0; i<7; i++){
           tg.startTone(ToneGenerator.TONE_DTMF_0, 150); // 150ms の鳴動
           try {
              Thread.sleep(150); // 150ms の Sleep
          } catch (InterruptedException e){ }
        }
    }
    
    
    @Override @SuppressLint("HandlerLeak") 
    protected void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        if(DEBUG)Log.i(tag, "onCreate( );");
        app = this;
        setContentView(R.layout.activity_main);
        
        cetCounter = (EditText)findViewById(R.id.cet_counter);
        hdrCFlash = new Handler( ){
            public void handleMessage(Message msg){
               cetCounter.setText(String.valueOf(ilCounter));
            }
        };
        cetCounter.setOnClickListener(new OnClickListener( ){
            @Override
            public void onClick(View v){
               cetCounter.setText("");
            }
        });
        
        cbStart = (Button)findViewById(R.id.cb_start);
        cbStart.setOnClickListener(new OnClickListener( ){
            @Override
            public void onClick(View v){
                try {
                   ilCounter = Integer.parseInt(cetCounter.getText( ).toString( ));
                } catch ( NumberFormatException e) {
                   ilCounter = 0;
                }
                if(0<ilCounter ){
                   scheduleService( );
                }
            }
        });
        
        cbCancel = (Button)findViewById(R.id.cb_cancel);
        cbCancel.setOnClickListener(new OnClickListener( ){
            @Override
            public void onClick(View v){
                cancelService( );
            }
        });
        
    }
  
    protected void scheduleService( ){
        if(DEBUG)Log.i(tag, "scheduleService( );");
        Context context = getBaseContext( );
        Intent intent = new Intent(context, MyService.class);
        PendingIntent pendingIntent 
          = PendingIntent.getService(
            context, -1, intent, 
            PendingIntent.FLAG_UPDATE_CURRENT);
        AlarmManager alarmManager 
          = (AlarmManager)context.getSystemService(ALARM_SERVICE);
        alarmManager.setInexactRepeating(
          AlarmManager.RTC, 
          System.currentTimeMillis( ),
          interval, pendingIntent);
    }
  
    protected void cancelService( ){
        if(DEBUG)Log.i(tag, "cancelService( );");
        synchronized(app) {
// ↑ この synchronized によって「ilCounter = 0」と それに関連する一連の Process の"Atomic"性を確保している。
// 注.「ilCounter = 0」と それに関連する一連の Process には非常に希薄ではあるが依存関係がある事に留意。
// 恐らく変数にアクセスされる側(この場合は app)を Monitor にすれば良いと思われる、Method に直に指定した場合は「synchronized(this)」と等価になるらしい。
// こんな簡単な Program で わざわざ synchronized を使う事も無いのだけど、
// 少し 複雑になって来ると必要になる事もあるので、その場合のサンプル的な意味合い。
            ilCounter = 0;
            Context context = getBaseContext( );
            Intent intent = new Intent(context, MyService.class);
            PendingIntent pendingIntent 
              = PendingIntent.getService(
                context, -1, intent, 
                PendingIntent.FLAG_UPDATE_CURRENT);
            AlarmManager alarmManager 
              = (AlarmManager)
              context.getSystemService(ALARM_SERVICE);
            alarmManager.cancel(pendingIntent);
        }
        hdrCFlash.sendEmptyMessage(0);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu){
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater( ).inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item){
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId( );
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
}


『res\layout\activity_main.xml』


<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.alarm0019_pkg.MainActivity" >

    <EditText
        android:id="@+id/cet_counter"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:ems="10"
        android:gravity="right"
        android:imeOptions="normal"
        android:inputType="numberDecimal"
        android:text="0"
        android:textAlignment="gravity"
        android:textColor="#000000" >
        <requestFocus />
    </EditText>
         
    
    <Button
        android:id="@+id/cb_start"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Start" />

    <Button
        android:id="@+id/cb_cancel"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Cancel" />

</LinearLayout >


『AndroidManifest.xml』


<?xml version="1.0" encoding="utf-8"?>
<manifest
    xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.alarm0019_pkg"
    android:versionName="1.0"
    android:versionCode="12" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="20" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" 
            android:launchMode="singleInstance" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <service android:name=".MainActivity$MyService"></service>
    </application>

</manifest>


<Number>: [000008C5]  <Date>: 2014/12/26 02:55:44
<Title>: Alarm (3) 改
<Name>: amanojaku@管理人



Alarm (3) 改

>キッチン・タイマー:指定された秒数をカウント・ダウンし、ゼロになったらシステム音を鳴らす。

"分"の入力を可能に、beep をバックグラウンド処理に。

とりあえずアプリケーション名は"Alarm0020_JFX"、プロジェクト名は"Alarm0020_Prj"、パッケージ名は"com.example.alarm0020_pkg"、"Activity"名は"MainActivity"、"Layout"名は"activity_main"としている、その他はデフォルトでスケルトンを作成。


『src/com.example.alarm0020_pkg/MainActivity.java』


package com.example.alarm0020_pkg;

import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.media.AudioManager;
import android.media.ToneGenerator;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View.OnFocusChangeListener;
import android.annotation.SuppressLint;
import android.app.AlarmManager;
import android.app.IntentService;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class MainActivity extends ActionBarActivity {

    static final String tag = "Log.Debug"; // フィルタリング用タグ
    static final boolean DEBUG = true; // false; // 
//↑ この"DEBUG"は予約語では無い、"Java"において"final"(定数)の場合は
//全部 大文字で記述するの事が推奨されているようだ。
//「DEBUG=true」に設定すれば「if(DEBUG)Log.i(〜)」によって"LogCat"に出力される事になる。

    static MainActivity app;
    static Handler hdrCFlash;
    static long ilMinute;
    static long ilSecond;
    static volatile long ilCounter; // volatile:最適化の抑制。
// ↑ "volatile"(最適化の抑制)により「Event、他の Thread」からの変数の可視性が保障されます。
// ただ"volatile"(最適化の抑制)で「Event、他の Thread」からの変数の正しい操作が保障されるわけではないので、過信するのは禁物です。
// 例えば「volatile int i」と宣言されていたとして「i++」と言う単純な命令が「メモリーからレジスターに読み取り、レジスターに1を加算、レジスターからメモリーに書き出し」と言う3個の命令として実行されるので、そこに"Atomic"性はありません。
// つまり 一見 単純に見える命令でも取りあえずは"Atomic"性は保障されないと考えておくベキ。
// "Atomic"性を確保したい場合は"synchronized"を使用する必要があります。

    EditText cetMinute;
    EditText cetSecond;
    Button cbStart;
    Button cbCancel;
    long ilInterval = 1000;
    
    public static class MyService extends IntentService {

        static final String serviceName = MyService.class.getSimpleName( );
        // getName(); // パッケージ名を含むクラス名
        // getSimpleName() // クラス名のみ
        
        public MyService( ) {
            super(serviceName);
            if(DEBUG)Log.i(tag, serviceName);
        }

        @Override
        protected void onHandleIntent(Intent intent) {
            if(DEBUG)Log.i(tag, "onHandleIntent( );");
            synchronized(app) {
// ↑ この synchronized によって「ilCounter--」、「if(ilCounter<=0)」、「app.cancelService( )」内の「ilCounter = 0」と それに関連する Process 、などの一連の Process の"Atomic"性を確保している。
// 恐らく変数にアクセスされる側(この場合は app)を Monitor にすれば良いと思われる、Method に直に指定した場合は「synchronized(this)」と等価になるらしい。
// こんな簡単な Program で わざわざ synchronized を使う事も無いのだけど、
// 少し 複雑になって来ると必要になる事もあるので、その場合のサンプル的な意味合い。
                ilCounter--;
                if(ilCounter<=0){
                    app.cancelService( );
                    beepThread( );
                }
            }
            hdrCFlash.sendEmptyMessage(0);
        }
      
    }
  
    static public void beep( ){
        ToneGenerator tg
          = new ToneGenerator(AudioManager.STREAM_SYSTEM, ToneGenerator.MAX_VOLUME);
        for(int i = 0; i<7; i++){
            tg.startTone(ToneGenerator.TONE_DTMF_0, 150); // 150ms の鳴動
            try {
               Thread.sleep(150); // 150ms の Sleep
            } catch (InterruptedException e){ }
        }
    }
  
    static public void beepThread( ){
        (new Thread(new Runnable( ){
            @Override
            public void run( ){
                // バックグランド処理
                beep( );
            }
        })).start( );
    }
  
    @Override @SuppressLint("HandlerLeak") 
    protected void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        if(DEBUG)Log.i(tag, "onCreate( );");
        app = this;
        setContentView(R.layout.activity_main);
        
        cetMinute = (EditText)findViewById(R.id.cet_minute);
        cetMinute.setOnClickListener(new OnClickListener( ){
            @Override
            public void onClick(View v){
                cetMinute.setText("");
            }
        });
        cetMinute.setOnFocusChangeListener(new OnFocusChangeListener( ){
            @Override
            public void onFocusChange(View v, boolean hasFocus){
                if(hasFocus){
                    cetMinute.setText("");
                }
            }
        });

        cetSecond = (EditText)findViewById(R.id.cet_second);
        cetSecond.setOnClickListener(new OnClickListener( ){
            @Override
            public void onClick(View v){
                cetSecond.setText("");
            }
        });
        cetSecond.setOnFocusChangeListener(new OnFocusChangeListener( ){
            @Override
            public void onFocusChange(View v, boolean hasFocus){
                if(hasFocus){
                    cetSecond.setText("");
                }
            }
        });

        hdrCFlash = new Handler( ){
            public void handleMessage(Message msg){
                cetMinute.setText(String.valueOf((long)Math.floor(ilCounter/60)));
                cetSecond.setText(String.valueOf(ilCounter%60));
            }
        };
        
        cbStart = (Button)findViewById(R.id.cb_start);
        cbStart.setOnClickListener(new OnClickListener( ){
            @Override
            public void onClick(View v){
                try {
                    ilMinute = Integer.parseInt(cetMinute.getText( ).toString( ));
                 } catch ( NumberFormatException e) {
                     ilMinute = 0;
                 }
                try {
                    ilSecond = Integer.parseInt(cetSecond.getText( ).toString( ));
                 } catch ( NumberFormatException e) {
                     ilSecond = 0;
                 }
                ilCounter = ilMinute*60+ilSecond;
                 if(0<ilCounter ){
                     scheduleService( );
                 }
            }
        });
        
        cbCancel = (Button)findViewById(R.id.cb_cancel);
        cbCancel.setOnClickListener(new OnClickListener( ){
            @Override
            public void onClick(View v){
                cancelService( );
            }
        });
        
    }
  
    protected void scheduleService( ){
        if(DEBUG)Log.i(tag, "scheduleService( );");
        Context context = getBaseContext( );
        Intent intent = new Intent(context, MyService.class);
        PendingIntent pendingIntent 
          = PendingIntent.getService(
          context, -1, intent, 
          PendingIntent.FLAG_UPDATE_CURRENT);
        AlarmManager alarmManager 
          = (AlarmManager)context.getSystemService(ALARM_SERVICE);
        alarmManager.setInexactRepeating(
          AlarmManager.RTC, 
          System.currentTimeMillis( ),
          ilInterval, pendingIntent);
    }
  
    protected void cancelService( ){
        if(DEBUG)Log.i(tag, "cancelService( );");
        synchronized(app) {
// ↑ この synchronized によって「ilCounter = 0」と それに関連する一連の Process の"Atomic"性を確保している。
// 注.「ilCounter = 0」と それに関連する一連の Process には非常に希薄ではあるが依存関係がある事に留意。
// 恐らく変数にアクセスされる側(この場合は app)を Monitor にすれば良いと思われる、Method に直に指定した場合は「synchronized(this)」と等価になるらしい。
// こんな簡単な Program で わざわざ synchronized を使う事も無いのだけど、
// 少し 複雑になって来ると必要になる事もあるので、その場合のサンプル的な意味合い。
            ilCounter = 0;
            Context context = getBaseContext( );
            Intent intent = new Intent(context, MyService.class);
            PendingIntent pendingIntent 
              = PendingIntent.getService(
              context, -1, intent, 
              PendingIntent.FLAG_UPDATE_CURRENT);
            AlarmManager alarmManager 
              = (AlarmManager)
              context.getSystemService(ALARM_SERVICE);
            alarmManager.cancel(pendingIntent);
        }
        hdrCFlash.sendEmptyMessage(0);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu){
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater( ).inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item){
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId( );
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
}


『res\layout\activity_main.xml』


<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.alarm0020_pkg.MainActivity" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <EditText
            android:id="@+id/cet_minute"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"
            android:ems="10"
            android:gravity="right"
            android:imeOptions="normal"
            android:inputType="numberDecimal"
            android:text="0"
            android:textAlignment="gravity"
            android:textColor="#000000" />

        <EditText
            android:id="@+id/cet_second"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"
            android:ems="10"
            android:gravity="right"
            android:imeOptions="normal"
            android:inputType="numberDecimal"
            android:text="0"
            android:textAlignment="gravity"
            android:textColor="#000000" />
        
    </LinearLayout>
    
    <Button
        android:id="@+id/cb_start"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Start" />

    <Button
        android:id="@+id/cb_cancel"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Cancel" />

</LinearLayout >


『AndroidManifest.xml』


<?xml version="1.0" encoding="utf-8"?>
<manifest
    xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.alarm0020_pkg"
    android:versionName="1.0"
    android:versionCode="12" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="20" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" 
            android:launchMode="singleInstance" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <service android:name=".MainActivity$MyService"></service>
    </application>

</manifest>


<Number>: [000008D2]  <Date>: 2014/12/28 09:58:19
<Title>: ActionBar「API Level 8」(Android OS 2.2)
<Name>: amanojaku@管理人



ActionBar「API Level 8」(Android OS 2.2)

端末にハードウェア・メニュー・キー(注.ハードウェア・キーボードではない)が有ると、ActionBarActivity のセールス・ポインットである、画面右上のメニュー・アイコン(three dots icon)が消えてしまうが(これは仕様だと言う事です)、消えないようにしたいし、ActionBarActivity は Android OS 3.0 以上からサポートされているが、Android OS 2.2 以上から使えるようにしたい。
ただし、アイコンが違うとか、メニューの表示位置が違うとかの違いはあるし、当然 機能も限定されるようだが…。

今回、Android 用 JavaFX プログラミングで参考にしたサイト。

Android - ActionBarにメニューの「…」を常時表示してサブメニューにアイコンを表示する - Qiita
http://qiita.com/takke/items/26993bcabd6866244fba

【Android】ActionBarを使ってみる @ (メニューボタン) - It’s now or never
http://inon29.hateblo.jp/entry/2014/03/09/162616

Androidで用意されているアイコン一覧 - 技術脳塗
https://sites.google.com/site/technoute/android/icon/drawable


とりあえずアプリケーション名は"ActionBar_API8_JFX"、プロジェクト名は"ActionBar_API8_Prj"、パッケージ名は"com.example.actionbar_api8_pkg"、"Activity"名は"MainActivity"、"Layout"名は"activity_main"としている、その他はデフォルトでスケルトンを作成。


『src/com.example.actionbar_api8_pkg/MainActivity.java』


package com.example.actionbar_api8_pkg;

import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.RelativeLayout;
import android.widget.TextView;

public class MainActivity extends ActionBarActivity {

    private MainActivity app;
    private Menu mainMenu;
    private RelativeLayout clRootLayout;
    private TextView ctvMessage;
   
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        app = this;
        setContentView(R.layout.activity_main);
        clRootLayout = (RelativeLayout)findViewById(R.id.cl_root_layout);
        ctvMessage = (TextView)findViewById(R.id.ctv_message);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater( ).inflate(R.menu.main, menu);
        mainMenu = menu;
        return true;
    }

    @Override 
    public boolean onKeyUp(int keyCode,KeyEvent event) {
        // boolean result = false; // true; //
        switch (keyCode) {
        case KeyEvent.KEYCODE_MENU:
            if (mainMenu != null) {
                mainMenu.performIdentifierAction(R.id.menu_primary, 0);
            }
            return true; // false; //
            //  break;
        default: 
            return super.onKeyUp(keyCode, event);
        }     
        // return false; // true; //
// ↑ イベントを消費した後、そのイベントを後続に引き継がせるかどうかを示す boolean 値
// つまり、 イベントのハンドリングが完了した後ここで動作を止めるよう指示する場合は true を返却します。
// イベントのハンドリングをしない場合、かつ(または) そのイベントを他のキーイベントリスナに引き継がせるよう指示する場合は false を返却します。
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
// 「UI(User Interface) Control」 のサイズが変化する場合、(Root Layout の)「invalidate( )」メソッドを実行してやらなければならないようだ。
        // boolean refresh = false; // true; //
        String vsMessageText;
// ↑ 実際は"vsMessageText"変数は必用無いのだけど 、あまりダラダラ長いと少々 解かりづらいので意図的に使っている。     

        synchronized(app) {
// ↑ この synchronized によって「R.id.mitem_〜」のデータを「ctvMessage」へ代入する一連の Process の"Atomic"性を確保している。
// 恐らく変数にアクセスされる側(この場合は app)を Monitor にすれば良いと思われる、Method に直に指定した場合は「synchronized(this)」と等価になるらしい。
// こんな簡単な Program で わざわざ synchronized を使う事も無いのだけど、
// 少し 複雑になって来ると必要になる事もあるので、その場合のサンプル的な意味合い。
            switch (item.getItemId( )) {
            case R.id.mitem_smile:
                vsMessageText = ((MenuItem)mainMenu.findItem(R.id.mitem_smile)).getTitle( ).toString( );
                ctvMessage.setText(vsMessageText);
                clRootLayout.invalidate( ); // 描画反映
                return true; // false; //
                //  break;
            case R.id.mitem_eyesturn:
                vsMessageText = ((MenuItem)mainMenu.findItem(R.id.mitem_eyesturn)).getTitle( ).toString( );
                ctvMessage.setText(vsMessageText);
                clRootLayout.invalidate( ); // 描画反映
                return true; // false; //
                //  break;
            case R.id.mitem_crying:
                vsMessageText = ((MenuItem)mainMenu.findItem(R.id.mitem_crying)).getTitle( ).toString( );
                ctvMessage.setText(vsMessageText);
                clRootLayout.invalidate( ); // 描画反映
                return true; // false; //
                //  break;
            default:
                return super.onOptionsItemSelected(item);
            }
        }
        // return false; // true; //
    }
}


『res\layout\activity_main.xml』


<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.actionbar_api8_pkg.MainActivity"
    android:id="@+id/cl_root_layout"
    android:background="#ffffff" >

    <TextView
        android:id="@+id/ctv_message"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="#bbbbbb"
        android:text="@string/hello_world"
        android:textColor="#000000" />

</RelativeLayout>


『AndroidManifest.xml』


<?xml version="1.0" encoding="utf-8"?>
<manifest
    xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.actionbar_api8_pkg"
    android:versionName="1.0" 
    android:versionCode="1" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="20" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name"
            android:launchMode="singleInstance" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>


<Number>: [000008F9]  <Date>: 2015/01/10 11:22:52
<Title>: SurfaceView(2) 改(3)
<Name>: amanojaku@管理人



SurfaceView(2) 改(3)

《参考》

SurfaceView(2) 改(2)
http://artemis.rosx.net/sjis/smt.cgi?r+izanami/&bid+0000083C&tsn+00000871&bts+2014/10/28%2002%3A03%3A17&
※「SurfaceView(2) 改(3)」との違いを見てみるのも良いかもしれません。
簡単に言えば「SurfaceView(2) 改(3)」において「canvas、surfaceHolder」に関する処理が 全て「RunningSurfaceView」クラスに記述されている、つまり「RunningDriver」クラスには一切「canvas、surfaceHolder」に関する処理が記述されてない。
つまり「RunningDriver」クラスを継承して別のクラスを記述すれば、ムダなく(この場合は「RunningDriver」クラスを)再利用できる事になる。


> 本来なら これら「canvas、surfaceHolder」は ここで記述するべきではなく、
> 別クラスを継承しで そこで記述してやるのが筋。

> 本来なら この「initialize( )」メソッドは
> この"RunningDriver"クラスでは抽象メソッドとし、
> 別クラスで それらのメソッドをオーバーライドしてやるのが筋。

> 本来なら下記「runningHeader( )、runningFooter( )」 メソッドは
> この"RunningDriver"クラスでは抽象メソッドとし、
> 別クラスで それらのメソッドをオーバーライドしてやるのが筋。

これらを実際にコーディングしている例。


とりあえずアプリケーション名は"A011_JFX"、プロジェクト名は"A011_Prj"、パッケージ名は"com.example.a011_pkg"としている、その他はデフォルトでスケルトンを作成。
ボタン"Accept"(アクセプト)は"Through"(スルー)状態の Runner を再スタートさせる。
ボタン"Through"(スルー)は Runner を"Through"(スルー)状態(runningEngine は動いているが Runner はスルーとなる)にする。
ボタン"notify"は"Wait"状態の Runner を再スタートさせる。
ボタン"Wait"は Runner を"Wait"状態にする。
ボタン"Create"(クリエイト)は"runningEngine"(Thread)を生成しスタートさせる。
ボタン"Destroy"(デストロイ)は"runningEngine"(Thread)を破棄する。


『src/com.example.a011_pkg/MainActivity.java』


package com.example.a011_pkg;

import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView.BufferType;
import android.util.Log;

public class MainActivity extends ActionBarActivity implements 
SurfaceHolder.Callback {

    static final String tag = "Log.Debug"; // フィルタリング用タグ
    static final boolean DEBUG = true; // false; // 
// ↑ この"DEBUG"は予約語では無い、"Java"において"final"(定数)の場合は
// 全部 大文字で記述するの事が推奨されているようだ。
// 「DEBUG=true」に設定すれば「if(DEBUG)Log.i(〜)」によって"LogCat"に出力される事になる。
    
    Thread running = null;
    boolean runningSW = true; // false; // 

    static int appLaunchMode;
    public static final int LAUNCH_CREATE = 1;
    public static final int LAUNCH_RESTART = 2;
    
    MainActivity app;
    int screenWidth, screenHeight;
    boolean surfaceChangedSW = false; // true; // 
    String vsMessage = "";
    EditText cetMessage;
    RunningSurfaceView runningSurfaceView;
    // Canvas canvas; 
    int[] cPalette = {
      Color.RED,Color.YELLOW,Color.MAGENTA,Color.GREEN,Color.CYAN,Color.BLUE };
// ↑ カラーの実態は Color オブジェクトではなく  int。
    
    public abstract class RunnerPrimitive {
        boolean ThroughSW = false; // true; // 
        public void run( ){ }
    }
    public abstract class RunnerFigure extends RunnerPrimitive {
        RunningSurfaceView runningSurfaceView; 
        Color color;
        Paint paint = new Paint( );
        int cx,cy,dx,dy;
    }
    public class RunnerCircle extends RunnerFigure {
        
        int radius = 30;
        
        public RunnerCircle(RunningSurfaceView RSV) {
            
            runningSurfaceView = RSV;
            if(DEBUG)Log.i(tag,
              "RunnerCircle( )"+"\n"+
              "screenWidth="+screenWidth+"\n"+
              "screenHeighth="+screenHeight+"\n"+
              "");

            cx = (int)Math.round(Math.random( )*screenWidth);
            cy = (int)Math.round(Math.random( )*screenHeight);
            if(DEBUG)Log.i(tag,
              "cx="+cx+"\n"+
              "cy="+cy+"\n"+
              "");
                 
            dx = (int)Math.signum(Math.round(Math.random( ))-.5)*10;
            dy = (int)Math.signum(Math.round(Math.random( ))-.5)*10;
            if(DEBUG)Log.i(tag,
              "dx="+dx+"\n"+
              "dy="+dy+"\n"+
              "");
                 
            int c = cPalette[(int)Math.round(Math.random( )*(cPalette.length-1))];
            paint.setStyle(Style.FILL);
            paint.setColor(c);
            if(DEBUG)Log.i(tag,
              "paint.set"+"\n"+
              "");

        }

        @Override
        public void run( ) {
            synchronized(runningSurfaceView) { 
                runningSurfaceView.canvas.drawCircle(
                  cx, cy, radius,paint);
                if( ! ThroughSW )  { 
                    if( (cx+dx)<0 | screenWidth<(cx+dx) ){
                        dx = -dx;
                    }
                    cx += dx;
                    if( (cy+dy)<0 | screenHeight<(cy+dy) ){
                        dy = -dy;
                    }
                    cy += dy;
                }
            }
        }
    }

    public abstract class RunningDriver
      implements Runnable {
       
        RunnerFigure[] runnerMembers = new RunnerFigure[5];
// ↑ 手抜きで配列にしているが、本来ならノードで連結させるのが筋。
        
        int runnerNumber;
        public Thread runningEngine = null;
        public boolean runningEngineSW = false; // true; // 
        public boolean waitSW = false; // true; // 
        long interval = 50;
        
        public RunningDriver( ){ }
        
        public void launch(int LaunchMode){
            switch (LaunchMode){
                case LAUNCH_CREATE:
                    initialize( );
                    runningEngineCreate( );
                break;    
                
                case LAUNCH_RESTART:
                    runningEngineCreate( );
                break;
                
                default:
            }
        }
        
        public abstract void initialize( );
        public abstract void runningHeader( );
        public abstract void runningFooter( );
        
        public void runnerAcceptAll( ){
           for( int i = 0; i<runnerMembers.length; i++){
               if( runnerMembers[i]!=null ){
                   runnerMembers[i].ThroughSW = false; // true; // 
               }
           }
        }
      
        public void runnerThroughAll( ){
            for( int i = 0; i<runnerMembers.length; i++){
                if( runnerMembers[i]!=null ){
                    runnerMembers[i].ThroughSW = true; // false; // 
                }
            }
        }
        
        public void runningEngineCreate( ) {
            runnerAcceptAll( );
            runningEngineSW = true; // false; // 
            waitSW = false; // true; // 
            // runningEngine = null;
            runningEngine = new Thread(this);
            runningEngine.start( );
        }
        
        public void runningEngineDestroy( ){
            try{
                runningEngine.interrupt( );
            } catch(NullPointerException e) {
                // e.printStackTrace( );
                if(DEBUG)Log.i(tag, "RunningDriver:runningEngineDestroy( ):NullPointerException;");
            }
        }
        
        public void run( ){
            if(DEBUG)Log.i(tag, "RunningDriver.run( );");
            while(
              runningEngine!=null &               
              runningEngineSW
            ){
                synchronized(this) { 
// ↑ この this は runningEngine では無く RunningDriver を継承している オブジェクトのインスタンス。
                        
                        try{
                        
                            runningHeader( );
                        for( runnerNumber = 0; runnerNumber<runnerMembers.length; runnerNumber++){
                               if( runnerMembers[runnerNumber]!=null ){
                                   runnerMembers[runnerNumber].run( );
                               }
                           }
                           runningFooter( );
                        } catch(NullPointerException e) {
                            // e.printStackTrace( );
                        if(DEBUG)Log.i(tag, "RunningDriver:run( ):NullPointerException;");
                            runningEngineSW = false; // true; //
                        }
                        
                    while(waitSW){
                        try{
                            this.wait( );
// ↑ この this は runningEngine では無く RunningDriver を継承している オブジェクトのインスタンス。
                        }catch(InterruptedException e){
                            // e.printStackTrace( ); 
                            if(DEBUG)Log.i(tag, "RunningDriver:run( ):InterruptedException;");
                            runningEngineSW = false; // true; //
                        }
                    }
                    
                    if( runningEngineSW ){
                        try{
                            Thread.sleep(interval);
// ↑ 「sleep(interval)」は指定された時間以上に待たされる場合があるようなので、
// 1回のループは「プログラムの処理時間+sleep(interval+α)」 となるから、
// 正確(完璧に正確無比と言う意味ではない)なタイマーを作りたい場合は
//「long time = System.currentTimeMillis( )」を使って一工夫が必要となる。                    
                        } catch(InterruptedException e) {
                            // e.printStackTrace( ); 
                            if(DEBUG)Log.i(tag, "RunningDriver:run( ):InterruptedException;");
                            runningEngineSW = false; // true; //
                        }
                    }
                }
                
            }
            runningEngine = null;
        }
    }
    
    public class RunningSurfaceView extends RunningDriver {
        public Canvas canvas;
        public SurfaceHolder surfaceHolder;
        
        public RunningSurfaceView( ){
           super( );
        }
        
        @Override
        public void initialize( ){
            for( int i = 0; i<runnerMembers.length; i++){
                runnerMembers[i] = new RunnerCircle(this);
            }
        }
      
        @Override
        public synchronized void runningHeader( ){
// ↑ Method に直に指定した場合は「synchronized(this)」と等価になるらしい。
            Paint bgPaint = new Paint();
            bgPaint.setStyle(Style.FILL);
            bgPaint.setColor(Color.WHITE);
            canvas = surfaceHolder.lockCanvas( );
            canvas.drawRect(
              0, 0, screenWidth, screenHeight,
              bgPaint);
        }
        
        @Override
        public synchronized void runningFooter( ){
// ↑ Method に直に指定した場合は「synchronized(this)」と等価になるらしい。
            surfaceHolder.unlockCanvasAndPost(canvas);
        }
        
    }
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        if(DEBUG)Log.i(tag, "onCreate( );");
        app = this;
        appLaunchMode = LAUNCH_CREATE;
         
        cetMessage = (EditText)findViewById(R.id.cet_message);
        vsMessage = vsMessage+"onCreate\n";
        cetMessage.setText(vsMessage, BufferType.NORMAL);
        
        runningSurfaceView = new RunningSurfaceView( );
// 「MainActivity」クラスの この「onCreate( )」コンストラクターでは
// まだ"SurfaceView"の生成が完了してない場合が有るようで、
// その時点で"Thread"が実行された場合
// 「surfaceHolder.lockCanvas( )」による"Canvas"の生成が"null"になってしまうので、
// 「RunningSurfaceView( )」コンストラクターには
// 「runningEngineCreate( )」("Thread"の生成・実行)は内包しない。
// 又、「RunnerCircle( )」 コンストラクター実行時には
// 「screenWidth、screenHeight」が設定されていなければならないので
// 「RunningSurfaceView( )」コンストラクターには内包せず、別途「initialize( )」に内包する。
// それら「initialize( )、runningEngineCreate( )」は「launch( )」に内包し「surfaceChanged( )」で実行する。
// ただし「launch( )」に内包された それら(「initialize( )、runningEngineCreate( )」)は"appLaunchMode"で実行の可否が決定される。
        
        if(DEBUG)Log.i(tag, "runningSurfaceView = new RunningSurfaceView( );");
        vsMessage = vsMessage+"runningSurfaceView = new RunningSurfaceView( )\n";
        cetMessage.setText(vsMessage, BufferType.NORMAL);
        
        /* ボタンを取り出す */
        Button cbAcceptAll = (Button)findViewById(R.id.cb_accept_all);
        /* ボタンにリスナーを登録する */
        cbAcceptAll.setOnClickListener(new OnClickListener( ) {
            @Override
            public void onClick(View v) {
                runningSurfaceView.runnerAcceptAll( );
            }
        });    
        
        /* ボタンを取り出す */
        Button cbThroughAll = (Button)findViewById(R.id.cb_through_all);
        /* ボタンにリスナーを登録する */
        cbThroughAll.setOnClickListener(new OnClickListener( ) {
            @Override
            public void onClick(View v) {
                runningSurfaceView.runnerThroughAll( );
            }
        });

        /* ボタンを取り出す */
        Button cbWait = (Button)findViewById(R.id.cb_wait);
        /* ボタンにリスナーを登録する */
        cbWait.setOnClickListener(new OnClickListener( ) {
            @Override
            public void onClick(View v) {
                runningSurfaceView.waitSW = true; // false; // 
            }
        });  
        
        /* ボタンを取り出す */
        Button cbNotify = (Button)findViewById(R.id.cb_notify);
        /* ボタンにリスナーを登録する */
        cbNotify.setOnClickListener(new OnClickListener( ) {
            @Override
            public void onClick(View v) {
                try{
                    synchronized(runningSurfaceView){
                        runningSurfaceView.waitSW = false; // true; //     
                        runningSurfaceView.notify( );
                    }
                }catch(IllegalMonitorStateException  e){ }
            }
        });  
        
        /* ボタンを取り出す */
        Button cbCreate = (Button)findViewById(R.id.cb_create);
        /* ボタンにリスナーを登録する */
        cbCreate.setOnClickListener(new OnClickListener( ) {
            @Override
            public void onClick(View v) {
                runningSurfaceView.runningEngineCreate( );
            }
        });    
        
        /* ボタンを取り出す */
        Button cbDestroy = (Button)findViewById(R.id.cb_destroy);
        /* ボタンにリスナーを登録する */
        cbDestroy.setOnClickListener(new OnClickListener( ) {
            @Override
            public void onClick(View v) {
                runningSurfaceView.runningEngineDestroy( );
            }
        });  

    }
    
    @Override
    protected void onRestart( ) {
        super.onRestart( );
        if(DEBUG)Log.i(tag, "onRestart( );");
        
        appLaunchMode = LAUNCH_RESTART;
    }
    
    @Override
    protected void onStart( ) {
        super.onStart( );
        if(DEBUG)Log.i(tag, "onStart( );");
        
        surfaceChangedSW = false; // true; //
        SurfaceView SV = (SurfaceView)findViewById(R.id.SV);
        SurfaceHolder SH = SV.getHolder();
        SH.addCallback(app);   
        // SV.setFocusable(true);
        // SV.requestFocus( );
        runningSurfaceView.surfaceHolder = SH;
    }
    
    @Override
    protected void onResume( ) {
        super.onResume( );
        if(DEBUG)Log.i(tag, "onResume( );");
    }
    
    @Override
    protected void onPause( ) {
        super.onPause( );
        if(DEBUG)Log.i(tag, "onPause( );");
    }

    @Override
    protected void onStop( ) {
        super.onStop( );
        if(DEBUG)Log.i(tag, "onStop( );");
        
        runningSurfaceView.runningEngineDestroy( );
        runningSurfaceView.surfaceHolder.removeCallback(app);
    }
    
    @Override
    protected void onDestroy( ) {
        super.onDestroy( );
        if(DEBUG)Log.i(tag, "onDestroy( );");
    }
    
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) { }

    @Override
    public void surfaceChanged(SurfaceHolder holder, 
     int format, int width, int height) {

       screenWidth = width;
       screenHeight = height;
       
       if(DEBUG)Log.i(tag,
         "surfaceChanged( );"+"\n"+
         "screenWidth="+screenWidth+"\n"+
         "screenHeighth="+screenHeight+"\n"+
         "");
       vsMessage = vsMessage+
         "screenWidth="+screenWidth+"\n"+
         "screenHeighth="+screenHeight+"\n"+
         "";
       cetMessage.setText(vsMessage, BufferType.NORMAL);
                 
        vsMessage = vsMessage+"surfaceChanged( )\n";
        cetMessage.setText(vsMessage, BufferType.NORMAL);
       
       if( ! surfaceChangedSW ){
           surfaceChangedSW = true; // false; //
// "surfaceChangedSW"がクリアーされない限りは、「surfaceChanged( )」 が2回以上呼ばれても、ここは1回しか実行されない。
           
           runningSurfaceView.launch(appLaunchMode);
       }
     
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) { }
    
}


『res\layout\activity_main.xml』


<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.a011_pkg.MainActivity" >

    <SurfaceView
        android:id="@+id/SV"
        android:layout_width="fill_parent"
        android:layout_height="200dp" />

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" >

        <Button
            android:id="@+id/cb_accept_all"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/AcceptAll" />

        <Button
            android:id="@+id/cb_through_all"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/ThroughAll" />
        
    </LinearLayout>

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" >

        <Button
            android:id="@+id/cb_notify"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/Notify" />

        <Button
            android:id="@+id/cb_wait"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/Wait" />

    </LinearLayout>

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" >

        <Button
            android:id="@+id/cb_create"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/Create" />

        <Button
            android:id="@+id/cb_destroy"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/Destroy" />

    </LinearLayout>

    <EditText
        android:id="@+id/cet_message"
        android:gravity="top"
        android:layout_width="fill_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:inputType="textMultiLine" >

        <requestFocus />
    </EditText>

</LinearLayout>


『res\values\strings.xml』


<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string name="app_name">A011_JFX</string>
    <string name="action_settings">Settings</string>
    <string name="AcceptAll">Accept</string>
    <string name="ThroughAll">Through</string>
    <string name="Notify">Notify</string>
    <string name="Wait">Wait</string>
    <string name="Create">Create</string>
    <string name="Destroy">Destroy</string>
    
</resources>


『AndroidManifest.xml』


<?xml version="1.0" encoding="utf-8"?>
<manifest
    xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.a011_pkg"
    android:versionName="1.0"
    android:versionCode="8" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="20" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name"
            android:launchMode="singleInstance" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

Block( Address 00000901 Identity 0000083C )










ページの表示順:{ 新しい順/ 古い順}.
初期・ページの表示・位置:{ 先頭ページ/ 末尾ページ}.
1ページ内のスレッド表示数:

   
   

管理者用 Password:

  




SMT Version 8.022(+A) Release M6.
Author : amanojaku.


- Rental Orbit Space -