
	Android版での注意点


はじめに
--------

Android NDKを利用して，spComponentを用いて開発したGUIアプリケーションを
Androidで動作させることができます．基本的に，すでにspComponentを用いて
開発済みのアプリケーションのソースコードをそのままで動かすという感じではなく，
ソースコードをAndroid用に改変して動かすことを想定しています．

ソースコードの互換性はある程度高いと思いますが，細かい挙動が結構異なります
（詳細は下記の「制約」の項を見て下さい）．

以下では，サンプルプログラムのビルド方法と，サンプルプログラムをベースに
新しいプロジェクトを作成する方法を説明しています．
Androidでの開発に精通している人は，サンプルプログラムを用いる必要は
ありません．その際には，コンパイル時に，#define ANDROIDを行う必要があります．
あるいは，サンプルプログラムのように，-DANDROIDオプションをjni/Android.mkの
LOCAL_CFLAGSに追加します．


動作環境
--------

Android SDKとAndroid NDKが正しくインストールされていることが必要です．まずは，
Googleの提供するNDKのサンプルプログラムがndk-buildによりビルドでき，
プログラムが正しく動作することを確認して下さい．また，サンプルプログラムは
Android Studioを用いて動作チェックを行っています．

このライブラリを使用するには，拙作のspBaseとspComponentの2つのライブラリが
別途必要になります．サンプルをそのままビルドするには，以下のようなディレクトリ
構成である必要があります．なお，OpengGLを用いる場合には，さらにspComponentEx
ライブラリも必要となります．OpenGLを用いない場合には，下記の spComponentEx
の記述の部分は不要です．

[ディレクトリ構成パターン1]

 include/
   sp/*.h （spBase，spComponent，spComponentEx の全てのヘッダファイル）
 spBase/
   android/
 spComponent/	    （このREADMEファイルがあるディレクトリ）
   android/
   example/
     android/

[ディレクトリ構成パターン2]

 spBase/
   sp/
   android/
 ../	    （このREADMEファイルがあるディレクトリ）
   android/
   example/
     android/
 spComponent/
   sp/
   example/
 spComponentEx/		（OpenGLを使用する場合）
   sp/

上記の「../」ディレクトリは，配布形態によっては [ディレクトリ構成パターン1] と
同様にspComponentディレクトリと統合されている場合があります．

spComponentに依存した不都合はそれほどないと思いますが，Androidの開発環境自体
が正常にインストールするために苦労することが多いですので，Androidの開発経験に
乏しい人はご注意下さい（例えば，インストール状態によってはndk-buildがまともに
動作しないとか，Android SDKのいくつかのバージョンではデフォルトでインストール
されるProgurardがまともに機能しないなど）．


サンプルのビルド
----------------

example/android にAndroid Studioのサンプルプロジェクトがあります．
通常のAndroidのNDKを用いたプロジェクトのビルド方法とほぼ同様にビルドできます．

なお，サンプルのビルドには，予めspBase（spBase/android）と
spComponent（spComponent/android）のスタティックライブラリ，そしてspComponent
のexampleのソースコードが必要です．具体的には，このREADMEのあるディレクトリから
見て，以下のファイル・ディレクトリが用意されている必要があります．

 android/obj/local/armeabi-v7a/libspc.a
 ../spBase/android/obj/local/armeabi-v7a/libspb.a
 ../spComponent/example （spComponentのexampleのソースコードがあるディレクトリ）

Android Studioのビルドまでの手順は，以下の通りです．

1. 「File」メニューから「New」>「Import Project...」を選択してサンプルプロジェクトを
  選択してインポートします．正確には，Android Studio専用のプロジェクトではなく，
  gradleのプロジェクトとして読み込むことになります．

2. Android Studioの初期設定の状態の場合は，読み込み後に自動的にビルドされます．
  ビルドされない場合は，「Build」メニューから「Make Project」を選択し，
  プロジェクトをビルドします．うまくビルドができない場合は，プロジェクトディレクトリの
  配下にある.soファイルを探して全部削除するとうまくいくことがあるようです．

3. 「Run」メニューから「Run '****'」を選択し，実行します．


サンプルのテンプレート
----------------------

example/android/template ディレクトリが，サンプルプログラムをビルドする
ためのテンプレートとなっています．このディレクトリを別名でコピーし，
以下の箇所を修正すると，Android Studio用の新しいサンプルプロジェクトを作成できます．

1. 「AndroidManifest.xml」ファイルの3行目のtemplateの部分を新しいサンプルの
  名前に変更

2. 「build.gradle」ファイルの27行目のtemplateの部分を新しいサンプルの名前に変更

5. 「res/values/strings.xml」ファイルの3行目のtemplateの部分を
  新しいサンプルの名前に変更

6. 「jni/Android.mk」の11行目のtemplateの部分を新しいサンプルの名前に変更

7. 「jni/Android.mk」の12行目のtemplate.cの部分を新しいサンプルの
  ソースファイル名に変更（例：test.c）．このテンプレートでは，下記のように
  実際のソースファイルを #include を使って読み込んでいます．
#include "../../../../../spComponent/example/track_bar.c"

8. 7. で変更したソースファイルの中身のtrack_bar.cの部分を実際に存在する
  サンプルのソースファイルに変更

9. これらの処理が全て終わった後，上の「サンプルのビルド」と同じ手順でビルド
  して下さい．


注意点
------
 - Android StudioやAndroid SDKのバージョン等によっては，ソースコードや
   全ての設定ファイルに異常がなくてもビルドに失敗したり，アプリケーションが
   立ち上がらないことがあります．

 - スレッドを利用したアプリケーションの場合は，端末を回転しても終了しない設定
   にして下さい．この設定を有効にしない場合，異常終了します．
   設定は，通常のAndroidアプリケーションと同様，AndroidManifest.xmlの
   <activity から > の間のどこかに，「android:configChanges="orientation|screenSize|keyboardHidden"」
   を追加します．


制約
----
 - モーダルダイアログであるメッセージボックス（spDisplayMessage等）は
   Android 7か8あたりで頻繁にクラッシュするようになりました．特に，トラックバーが
   存在している場合にメッセージボックスを表示すると高い確率でクラッシュするようになりました．
   この問題の解決には時間がかかると思われるため，当面はAndroidでは
   メッセージボックスを使わないようにするぐらいしか解決方法はありません．
 
 - スレッドからGUI関連の関数を直接呼び出すと（example/thread.cなど）
   アプリケーションが異常終了します．スレッドからGUI関連の関数を呼び出したい
   場合は，example/thread_event.cのように，ユーザーイベントを用いて間接的に
   呼び出すようにして下さい．

 - メニューにおいて，サブメニューは機能しません．Android自体の制約です．
   実際には，Android端末のほとんどは小型端末のため，深い階層のメニューはかなり
   使いづらいと思いますので，大きな制約ではないと考えています．

 - 通常のC言語でexitを呼び出した場合などと異なり，spQuitを呼び出して
   アプリケーションを終了した後は，その後も処理が続けられます．ですので，
   spQuitの直後に処理は書かないで下さい．spComponentの関数を呼び出すと
   異常終了します．Androidでは，exit関数の呼び出しは推奨されないためです．

 - グローバル変数・スタティック変数の値は，アプリケーションが終了しても保持される
   ことがあります．基本的には，spMain関数などで初期化をするようにして下さい．

 - spDispatchEvent関数（example/loop_test.cなどで使用）は動作しません．

 - モーダルウィンドウに付属しているボタン（OKボタン・キャンセルボタンなど）は，
   他の環境とは異なり，クリックするとウィンドウを閉じる仕様になっています．
   ただし，モーダルウィンドウの場合はウィンドウを閉じる関数が何もしない
   仕様になっているため，他の環境とソースコードを共有することは可能です．

 - モーダルウィンドウを用いる場合（ウィンドウポップアップ後に
   ウィンドウポップダウンまで返ってこない関数を用いる場合），それが開いている
   間に別のモーダルウィンドウを開くことはできません．
   アプリケーションが固まります．Androidの制約もあり，対処ができませんでした．
   同じ理由で，モーダルウィンドウが開いている間はモーダルウィンドウ以外の
   GUIを制御する関数を呼び出すことはできません．モーダルウィンドウ内のGUI
   パーツは制御可能です．

 - ホームボタンや戻るボタンを押した場合には，アプリケーションが終了するように
   してあります．これは，終了しないようにした場合，スレッドアプリケーションに
   おいて再開後にアプリケーションが正常に機能しなくなるためです．

