libGDXでプラットフォーム独自の機能を呼び出す

　libGDXはマルチプラットフォーム対応なので、ツールでプロジェクトを生成すると、各プラットフォーム向けのプロジェクトと共通プロジェクト(Core)が生成されます。
　通常は、共通プロジェクトのみを編集し、各プラットフォーム向けのプロジェクトでビルドするだけでOKです。

　しかしプラットフォーム独自の機能を利用する場合は、各プラットフォーム側のコードを変更する必要があります。
　アプリ起動時のみの処理であれば特に問題はありませんが、アプリ実行中(Coreでの処理中)に各プラットフォーム毎のコードを呼び出す場合は一工夫必要です。
　この方法について解説します。

### 想定される用途
・広告SDKの呼び出し
・アプリ内課金処理の呼び出し
・libGDXが対応していないセンサー値の取得

など

# 作成内容
　画面をタッチすると各プラットフォームネイティブのメッセージダイアログを表示します。

　Core側からタイトルと本文を指定して呼び出すと、その内容でダイアログを開きます。
　[OK]ボタンを押すと閉じます。

　今回は、Android版とデスクトップ版で作成しました。
　

# 方針
　メッセージ表示処理のinterface `MessageBoxShowable` を定義し、これを実装したクラスのインスタンスをCore側のコンストラクタで受け取るにします。
　画面がタッチされたらこのインスタンスのメソッドを呼び出してメッセージダイアログを表示します。（この処理は各プラットフォーム側に記述します）


1.　メッセージ表示処理のinterface `MessageBoxShowable` を定義します。
2.　Core側のクラス `MyGdxGame` に、`MessageBoxShowable`を実装したクラスのインスタンスをパラメータとして受け取るコンストラクタを追加します。
    2-1. コンストラクタでは受け取ったインスタンスを保存
    2-2. `MessageBoxShowable` を渡されない場合のためデフォルトコンストラクタも追加します。
3.　各プラットフォーム側のコードでは、`MessageBoxShowable`を実装したクラスを作成します。
    3-1. クラスでは、`showMessageBox` メソッドにメッセージダイアログ表示コードを記述します。
    3-1. `MyGdxGame`の生成時にパラメータとして渡します。
4. Core側のクラスで、画面タッチ時に、`MessageBoxShowable`の`showMessageBox` メソッドをコールします。


# 作成

プロジェクトは、[libGDX 1.0以降でのプロジェクト作成方法(Gradle＋Eclipse)](http://qiita.com/fslasht/items/de3bdde459345fbaa66e)の記事で作成したものを使用します。

## インターフェース
Coreにインターフェースを定義
メッセージダイアログ表示用の`MessageBoxShowable`メソッドを持ちます。

```java:MessageBoxShowable.java
package com.dokokano.gdxappwithseveralmsgbox;

public interface MessageBoxShowable {
	public void showMessageBox(String title,String message);
}
```

## Coreコード
`GdxAppWithSeveralMsgBox-core` プロジェクト
共通のコードです。

```java:MyGdxGame.java
package com.dokokano.gdxappwithseveralmsgbox;

import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;

public class MyGdxGame extends ApplicationAdapter {
	SpriteBatch batch;
	Texture img;

	MessageBoxShowable messageBoxShowable_;

	public MyGdxGame()
	{
		messageBoxShowable_ = null;
	}
	public MyGdxGame(MessageBoxShowable messageBoxShowable) {
		messageBoxShowable_ = messageBoxShowable;
	}

	@Override
	public void create () {
		batch = new SpriteBatch();
		img = new Texture("badlogic.jpg");
	}

	@Override
	public void render () {
		Gdx.gl.glClearColor(1, 0, 0, 1);
		Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
		batch.begin();
		batch.draw(img, 0, 0);
		batch.end();

		if ( Gdx.input.justTouched() ) {
			if ( messageBoxShowable_!=null) {
				messageBoxShowable_.showMessageBox("ShowMessageBox", "Hello GDX!");
			}
		}
	}
}
```


### コンストラクタ
`MessageBoxShowable`を実装したクラスのインスタンスをパラメータとして受け取るコンストラクタを追加します。
コンストラクタでは受け取ったインスタンスを`messageBoxShowable_`に保持

```java
	MessageBoxShowable messageBoxShowable_;

	public MyGdxGame()
	{
		messageBoxShowable_ = null;
	}
	public MyGdxGame(MessageBoxShowable messageBoxShowable) {
		messageBoxShowable_ = messageBoxShowable;
	}
```

###　メッセージダイアログ表示呼び出し

画面タッチ時に、メッセージダイアログ表示メソッドを呼び出しています。
※ インスタンスが登録されていない場合はnullチェックして呼び出さない。
```java
		if ( Gdx.input.justTouched() ) {
			if ( messageBoxShowable_!=null) {
				messageBoxShowable_.showMessageBox("ShowMessageBox", "Hello GDX!");
			}
		}
```


## Android版のコード
`GdxAppWithSeveralMsgBox-Android` プロジェクト

```java:AndroidLauncher.java
package com.dokokano.gdxappwithseveralmsgbox.android;

import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.os.Handler;

import com.badlogic.gdx.backends.android.AndroidApplication;
import com.badlogic.gdx.backends.android.AndroidApplicationConfiguration;
import com.dokokano.gdxappwithseveralmsgbox.MessageBoxShowable;
import com.dokokano.gdxappwithseveralmsgbox.MyGdxGame;

public class AndroidLauncher extends AndroidApplication {
	Handler handler_ = new Handler();

	@Override
	protected void onCreate (Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();
		initialize(new MyGdxGame( new MessageBoxShower() ), config);
	}

	class MessageBoxShower implements MessageBoxShowable {
		@Override
		public void showMessageBox(final String title, final String message) {
			handler_.post(new Runnable() {

				@Override
				public void run() {
				    AlertDialog.Builder alertDialog=new AlertDialog.Builder(AndroidLauncher.this);
				    alertDialog.setTitle(title);
				    alertDialog.setMessage(message);
				    alertDialog.setPositiveButton("OK",new DialogInterface.OnClickListener() {
				        public void onClick(DialogInterface dialog,int whichButton) {
				        	setResult(RESULT_OK);
				        }
				    });
				    alertDialog.create();
				    alertDialog.show();
				}
			});
		}
	}
}
```
 
　`MessageBoxShower` クラスを定義しており、共通クラスの`MyGDXGame`生成時にインスタンスをパラメーターとして渡しています。
　ダイアログ表示にはAlertDialogを利用しています。
　Coreの処理から呼び出された場合は、UIスレッドではないのでHandlerを使用して実行しています。

### 実行画面
![Screenshot_2014-05-07-16-32-33.png](https://qiita-image-store.s3.amazonaws.com/0/42140/6910c6af-f4d6-896e-3ff3-31c83f255ca1.png)

Androidネイティブのダイアログが表示されるのがわかります。


　
## Desktop版(Windows/OS X等)のコード
`GdxAppWithSeveralMsgBox-Desktop` プロジェクト

```java:DesktopLauncher.java
package com.dokokano.gdxappwithseveralmsgbox.desktop;

import org.lwjgl.Sys;

import com.badlogic.gdx.backends.lwjgl.LwjglApplication;
import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration;
import com.dokokano.gdxappwithseveralmsgbox.MessageBoxShowable;
import com.dokokano.gdxappwithseveralmsgbox.MyGdxGame;

public class DesktopLauncher {
	public static void main (String[] arg) {
		LwjglApplicationConfiguration config = new LwjglApplicationConfiguration();
		new LwjglApplication(new MyGdxGame( new MessageBoxShower() ), config);
	}

	static class MessageBoxShower implements MessageBoxShowable {
		@Override
		public void showMessageBox(String title, String message) {
			Sys.alert(title, message);
		}
	}
}
```
 
　`MessageBoxShower` クラスを定義しており、共通クラスの`MyGDXGame`生成時にインスタンスをパラメーターとして渡しています。
　ダイアログ表示には、Desktop版のバックエンドであるlwjglのSysクラスの[alertメソッド](http://www.lwjgl.org/javadoc/org/lwjgl/Sys.html#alert(java.lang.String, java.lang.String))を利用しています。

### 実行画面 ※ Windowsで実行

![スクリーンショット 2014-05-07 16.12.29.png](https://qiita-image-store.s3.amazonaws.com/0/42140/6f0f6d88-b8d7-456b-9698-959cb36cb004.png)


↓（クリックすると）

![スクリーンショット 2014-05-07 16.21.10.png](https://qiita-image-store.s3.amazonaws.com/0/42140/02967906-fb3a-edbd-a3e1-c635dc910580.png)

Windowsネイティブのダイアログが表示されるのがわかります。

### 実行画面 ※ OS Xで実行
![スクリーンショット 2014-05-08 10.24.59.png](https://qiita-image-store.s3.amazonaws.com/0/42140/4834ca65-7a2e-266d-451f-353794b7c65b.png)

OS Xネイティブのダイアログが表示されるのがわかります。


## その他のプラットフォームで実行した場合
今回は実装していないので、タッチしてもなにもおこりません。
※ コンストラクタで渡していないのでインスタンスがnull。
このように特定のプラットフォームのみに対応した機能を実装することが出来ます。