Re:0から始めるAndroid開発 ~いろんなフレームワークを使ってみる(8/25完了)~

# はじめに
この記事は [Android Advent Calendar 2019](https://qiita.com/advent-calendar/2019/android) の6日目です！

普段、Androidアプリケーションをどの言語どのフレームワークetc..を使って開発していますか?
自分は `Android Studio + Java` や `Unity + C#` で開発することが多いです
思えば自分が触ったことが無いフレームワークはたくさんありますが、自分が開発したいもの合わせて、よりベストな環境を選んでおきたい身としてはいろんなフレームワーク、言語を知って触っておくに越したことは無いのはエンジニアとしては当然だと思ってます。
なので、いろんなフレームワークを使って **同じ動作をする** Androidアプリを作成します！

# TL;DR
Androidアプリケーション開発のフレームワーク一覧

| ﻿フレームワーク  | 言語                          | 公式ページ                                                 | IDE                      | 一言特徴                   | 実装済(死に戻り) |
|-----------------|-------------------------------|------------------------------------------------------------|--------------------------|----------------------------|------------------|
| Android Studio  | Java/Kotlin/C++               | https://developer.android.com/studio/                      | Android Studio           | ネイティブアプリケーション | ✅                |
| Unity           | C#                            | https://unity3d.com/jp/unity                               | Unity Editor             | ゲームエンジン             | ✅                |
| Processing      | Java                          | https://processing.org/                                    | Processing               | グラフィックフレームワーク | ✅                |
| openFrameworks  | C++                           | https://openframeworks.cc/                                 | Android Studio           | グラフィックフレームワーク | ✅                |
| Cordova         | HTML5+JavaScript+CSS          | https://cordova.apache.org/                                | Visual Studio(Win)       | クロスプラットフォーム     | ✅                |
| React Native    | Javascript/TypeScript         | https://facebook.github.io/react-native/                   | 特になし                 | クロスプラットフォーム     | ✅                |
| Xamarin.Form    | C#/F#                         | https://dotnet.microsoft.com/apps/xamarin                  | Visual Studio            | クロスプラットフォーム     | ✅                |
| Xamarin.Android | C#/F#                         | https://dotnet.microsoft.com/apps/xamarin                  | Visual Studio            | ネイティブアプリケーション | ✅                |
| Unreal Engine   | C++/UnrealScript              | https://www.unrealengine.com/                              | Unreal Editor            | ゲームエンジン             | ❌                |
| Flutter         | Dart                          | https://flutter.dev/                                       | Android Studio           | クロスプラットフォーム     | ❌                |
| Cocos2d-x       | C++/Lua/JavaScript/TypeScript | https://www.cocos.com/en/                                  | Cocos Creator            | ゲームエンジン             | ❌                |
| Monaca          | HTML5+JavaScript              | https://ja.monaca.io/                                      | ブラウザ/Monaca Localkit | クロスプラットフォーム     | ❌                |
| DXライブラリ    | C++                           | https://dxlib.xsrv.jp/                                     | Android Studio           | ゲームエンジン             | ❌                |
| Qt              | C++                           | https://www.qt.io/                                         | Qt Creator IDE           | クロスプラットフォーム     | ❌                |
| ionic           | JavaScript                    | https://ionicframework.com/                                | Ionic Studio             | クロスプラットフォーム     | ❌                |
| Titanium        | JavaScript                    | https://www.appcelerator.com/Titanium/                     | Appcelerator Studio      | クロスプラットフォーム     | ❌                |
| NativeScript    | TypeScript/JavaScript         | https://www.nativescript.org/                              | VSCode/WebStorm          | クロスプラットフォーム     | ❌                |
| Weex            | JavaScript                    | https://weex.apache.org/                                   | 特になし                 | クロスプラットフォーム     | ❌                |
| meteor          | JavaScript                    | https://www.meteor.com/                                    | 特になし                 | クロスプラットフォーム     | ❌                |
| Vue Native      | JavaScript                    | https://vue-native.io/                                     | 特になし                 | クロスプラットフォーム     | ❌                |
| Defold          | Lua                           | https://defold.com/                                        | Defold editor            | ゲームエンジン             | ❌                |
| Godot           | GDScript                      | https://godotengine.org/                                   | Godot Engine             | ゲームエンジン             | ❌                |
| SCADE           | Swift                         | https://www.scade.io/                                      | Scade IDE                | クロスプラットフォーム        | ❌                |
| Kotlin Native   | Kotlin                        | https://kotlinlang.org/docs/reference/native-overview.html | Android Studio           | クロスプラットフォーム     | ❌                |
| AndEngine       | Java                          | http://www.andengine.org/                                  | IntelliJ IDEA            | ゲームエンジン             | ❌                |

# 作るもの
画面にただ`Hello World`と表示しても面白くないので、ボタンを押すと背景の色が変わるアプリを作ります。
`UI要素がどのように設置できるか` `ボタンイベントをどのように取得できるか` `Viewはどのように描画できるか` 、という点をみれるので良いチュートリアルだと思います
![output.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/a937f4dd-a26a-da0c-343e-4c0929e01a3f.gif)

# Android Studio
![Android](https://developer.android.com/studio/images/home/android-studio-logo.svg)

- Google謹製のAndroidプラットフォーム向けアプリ開発用の統合開発環境
- この環境が出るまでは、Eclipse + ADT (Android Developer Tools)でAndroidアプリの開発が行われていた
- なにより公式、[ドキュメント](https://developer.android.com/studio/intro)もツールも揃っている
- ネイティブアプリケーションを作りたいなら王道

## Java
まずは、JavaでAndroidアプリの作成を行います

0. Android Studioのインストール(説明は割愛します

1. Android Studioを立ち上げて、今回は新しくアプリを作成するので`Start a new Android Studio project`を選びます。最近開いたプロジェクトは左に表示されています
![alt](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/3c84726d-04a5-baff-dc2e-c1372b771353.png)

2. ボタンを押したら色が変わるだけのアプリなので`Empty Activity`を選択します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/73fb9686-234e-4079-21c7-11253ca8d2cb.png)

3. 必要な情報を入力します。 `Name` はアプリ名を入れます。 `Save Location` はプロジェクトを設置するディレクトリパスです。(既にプロジェクトが存在する場合は `already exists...` と警告してくれます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/0dcb2b60-18f4-1f27-a8e5-ad4e684147c7.png)

`Finish`を押すとAndroidアプリのプロジェクトが生成されます
生成されたファイルはざっと以下の感じになります

```bash:androidアプリプロジェクト
AndroidStuidoJava
├── app
│   ├── build.gradle
│   └── src
│       └── main
│           ├── AndroidManifest.xml
│           ├── java
│           │   └── jp
│           │       └── cha84rakanal
│           │           └── hellotogglecolor_studio_java
│           │               └── MainActivity.java
│           └── res
│               ├── drawable
│               │   └── ic_launcher_background.xml
│               ├── layout
│               │   └── activity_main.xml
│               └── values
│                   ├── colors.xml
│                   ├── strings.xml
│                   └── styles.xml
├── build.gradle
├── gradle.properties
├── local.properties
└── settings.gradle
```

4.プロジェクトが生成されたらボタン実装する前に兎にも角にも一旦起動します。起動には上部の`緑の▶マーク`を押すか、`Ctrl + R`を押します。その後、インストールするデバイスを選んで`OK`を押すと、ビルドされインストールされ起動します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/f5406741-b256-196c-51c1-169e4bd71b31.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/603f67c3-5514-dd02-3a1d-615e2116bb83.png)

### ボタンを実装
アプリが動くことを確認できたらボダンを実装していきます

`res/layout/activity_main.xml` を開いて次の内容に変更します。するとボタンが画面中央に配置された画面が構成されます

```xml:activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<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"
    tools:context=".MainActivity">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="Hello World!" />

</RelativeLayout>
```

### ボタンがクリックしたことを検知
設置したボタンはこのままではただのボタンなので、プログラムでボタンが押されたことを確認できるようにします。

`MainActivity.java` に引数に`View`クラスを1個を持ち返り値`void`の適当なメソッドを作成します

```java:MainActivity.java
package jp.cha84rakanal.hellotogglecolor_studio_java;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;

public class MainActivity extends Activity {

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

    void onButtonClick(View v){
        Log.v(MainActivity.class.getSimpleName(),"onButtonClick");
    }
}
```

`Log.v` はログを出力するメソッドでボタンを押すと `onButtonClick`とログに表示されます
ボタンを押したらどのメソッドを実行するか、今はわからないので、 `activity_main.xml`で指定します`Button` 要素に `android:onClick`プロパティを追加して作成した適当なメソッド名を渡します

```xml:activity_main.xml
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:onClick="onButtonClick"
        android:text="Hello World!" />
```

これで、ボタンを押すとログに`onButtonClick`と表示するアプリになりました
ログはターミナルで、`adb logcat`コマンドを実行するか、Android Studioの`Logcat`を使います
Logのタグに `MainActivity.class.getSimpleName()` を指定しているのでフィルターに`MainActivity`を打つと、`onButtonClick`のログだけを見れます
※ターミナルでのフィルタリング `adb logcat -s MainActivity:*`
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/9cd29cd8-6d74-c210-b7db-e643c7720796.png)

### 背景の色を変更
残りは背景の色を変えるだけです
`activity_main.xml`の`RelativeLayout` 要素に `android:background`プロパティを追加して色を指定します。色の指定は`#[透明度00~FF][赤00~FF][緑00~FF][青00~FF]`です
MainActivity.javaから参照できるように、IDをつけておきます

```xml:activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/back"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#FFFF0000"
    tools:context=".MainActivity">
```
`MainActivity.java`では、`findViewById`を使って、先程IDをつけた要素を取得して `setBackgroundColor`を使って色を変える部分を実装します。

```java:MainActivity.java
package jp.cha84rakanal.hellotogglecolor_studio_java;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;

public class MainActivity extends Activity {

    private boolean mToggle = true;

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

    void onButtonClick(View v){
        Log.v(MainActivity.class.getSimpleName(),"onButtonClick");
        mToggle = !mToggle;
        findViewById(R.id.back).setBackgroundColor( mToggle? 0xFFFF0000 : 0xFF0000FF);
    }
}
```

これでボタンを押すと 赤から青、青から赤に色が変わるアプリができました！
![output.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/a937f4dd-a26a-da0c-343e-4c0929e01a3f.gif)

## Kotlin
引き続いて、Android StudioでKotlinを使って同じアプリを作っていきます
Android Studioでは、プロジェクトの中に `モジュール` という単位で、アプリのプロジェクトやライブラリなどのプロジェクトが存在します。(デフォルトだとプロジェクトを作成した段階でのアプリのモジュール名は `app` )
次は新しくプロジェクトを作らずに現在のプロジェクトにKotlinのアプリのモジュールを追加します

1. File > New > New Module... を開き、アプリなので `Phone & Tablet Module`を選択します 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/76d2e85f-08d8-9f3d-7d51-cae96066b31b.png)

2. 必要な情報を入力します。`Module Name`はモジュールの名前です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/e30e433a-ddfe-f445-88de-b8b9c858e280.png)

3. Javaのときと同じく`Empty Activity`を選択します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/eeebb451-37a4-6acc-5988-070214462a5e.png)

4. Source Languageを`Kotlin`にします。選択するだけでJavaもKotlinも使えるのはAndroid Studio素晴らしい!
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/d07bcf28-2c4a-998f-b648-c95ed08c61a1.png)

`Finish`を押すとAndroidアプリのモジュールが生成されます
先程作ったプロジェクトの中に、hellotogglecolor_studio_kotlin ディレクトリができてると思います

```bash:androidアプリプロジェクト
AndroidStuidoJava
├── app <-- さっきのJavaでのアプリ
├── hellotogglecolor_studio_kotlin <-- これから作るKotlinのアプリ
├── build.gradle
├── gradle.properties
├── local.properties
└── settings.gradle
```
ただ色が変わるだけのアプリでは、JavaとKotlinでの書き方がちょっと違うぐらいなので、別の方法で実装すすめていきます

### ボタンを実装
すべて`MainActivity.kt`で実装します
`MainActivity`におけるルートViewは`ConstraintLayout`でその子に`Button`があり、センタリングは上下左右の制約で行います。

制約をKotlinで書くと凄い大変なので、極力XMLでレイアウトを組むのが良さそうです...

```kotlin:MainActivity.kt
package jp.cha84rakanal.hellotogglecolor_studio_kotlin

import android.app.Activity
import android.os.Bundle
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
import android.widget.Button
import android.view.View

class MainActivity : Activity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val cLayout = ConstraintLayout(this)
        val button = Button(this)
        cLayout.addView(button)

        val viewId = View.generateViewId()
        button.id =  viewId
        button.text = "Hello World!"

        val constraintSet = ConstraintSet()
        constraintSet.clone(cLayout)

        // android:layout_width="wrap_content"
        constraintSet.constrainHeight(button.id,
                ConstraintSet.WRAP_CONTENT)

        //android:layout_height="wrap_content"
        constraintSet.constrainWidth(button.id,
                ConstraintSet.WRAP_CONTENT)

        // app:layout_constraintBottom_toBottomOf="parent"
        constraintSet.connect(
                button.id,
                ConstraintSet.BOTTOM,
                ConstraintSet.PARENT_ID,
                ConstraintSet.BOTTOM,
                0)

        // app:layout_constraintLeft_toLeftOf="parent"
        constraintSet.connect(
                button.id,
                ConstraintSet.LEFT,
                ConstraintSet.PARENT_ID,
                ConstraintSet.LEFT,
                0)

        // app:layout_constraintRight_toRightOf="parent"
        constraintSet.connect(
                button.id,
                ConstraintSet.RIGHT,
                ConstraintSet.PARENT_ID,
                ConstraintSet.RIGHT,
                0)

        // app:layout_constraintTop_toTopOf="parent"
        constraintSet.connect(
                button.id,
                ConstraintSet.TOP,
                ConstraintSet.PARENT_ID,
                ConstraintSet.TOP,
                0)

        constraintSet.applyTo(cLayout)

        // ConstraintLayout set on ContentView
        setContentView(cLayout)
    }
}
```

これでボタンが中央に実装されました。

### ボタンがクリックしたことを検知
ボタンのクリック検知には`OnClickListener`を使います
`onCreate`メソッドの中の`button`の定義の後に次のコードを加えます

```kotlin:MainActivity.kt
        button.setOnClickListener {
            Log.v(MainActivity::class.java.simpleName, "onButtonClick")
        }
```
これで、ボタンを押すとログに`onButtonClick`と表示するアプリになりました

### 背景の色を変更
背景色だけはJavaとほとんど変わらず、`setBackgroundColor`を使えばできます
Kotlinでは三項演算子がなく、ifを式として扱えるのは特徴的な気がします

```kotlin:MainActivity.ktの上部
package jp.cha84rakanal.hellotogglecolor_studio_kotlin

import android.app.Activity
import android.graphics.Color
import android.os.Bundle
import android.util.Log
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
import android.widget.Button
import android.view.View

class MainActivity : Activity() {

    private var mToggle = true

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val cLayout = ConstraintLayout(this)
        cLayout.setBackgroundColor(Color.RED)
        val button = Button(this)
        cLayout.addView(button)

        val viewId = View.generateViewId()
        button.id =  viewId
        button.text = "Hello World!"

        button.setOnClickListener {
            Log.v(MainActivity::class.java.simpleName, "onButtonClick")
            mToggle = !mToggle
            cLayout.setBackgroundColor(if(mToggle) Color.RED else Color.BLUE)
        }
```

見た目は、`Java`で作られたのと変わらなかったです...

## C++
Android Studioで使える言語は、`Java` `Kotlin` だけではありません。 [NDK](https://developer.android.com/ndk?hl=ja)(Native Development Kit)を利用すれば `C/C++` でも開発ができます
いままでJava/Kotlinで開発していた `Activity` をまるごと実装することができるので、今回はNativeActivityを使って、目的のアプリをつくります。

0. NDKを使える環境をインストールします。 Tools > SDK Managerを使って、NDK/CMakeをインストールします。(File > Project Structureからもダウンロードできます)
`File > Project Structure` を開いて、`Android NDK Location` にNDKをインストールしたディレクトリパスが指定されていればOKです
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/0c534f20-899d-2342-84a6-bc919a1118a2.png)

1. 一からプロジェクトを作成すると大変なので、既にできているサンプルを改造します。 `File > New > Import Module...`を開き、検索窓に`Native`と打ち込みます。するとサンプルの一覧に`Ndk > Native Activity` とあるのでそれを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/85767481-966a-fd47-75c9-196347fedccb.png)

2. 必要な情報を入力します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/afc1e74c-a816-935b-bdd8-ee541543147b.png)

`Finish` を押すとサンプルが[GitHub](https://github.com/android/ndk-samples/tree/master/native-activity)からクローンされます。

3. 自動でプロジェクトが開くので、 `File > Sync Project with Gradle Files` を押します。それが終わったら兎にも角にもビルドしてアプリを`RUN`しましょう

![output.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/e6ade018-fb92-19f4-692a-9a039a6927aa.gif)

### ボタンを実装
これからボタンを実装していきます。`C++`だけで実装されたアプリのソースは、`app/src/main/cpp/main.cpp`だけなので、ボタンも描画もここに実装していくしかなさそうです。しかし、[TeapotのNDKサンプル](https://github.com/android/ndk-samples/tree/master/teapots)では、Java側でUIが書かれているので参考にしていきます。

まずは、Java側のActivityを実装していきます。
`app/src/main`に`java`ディレクトリを作成して、`java`ディレクトリにActivityを作成します。`java`ディレクトリを右クリックして `New > Activity > Empty Activity`を選択します。パッケージ名はここでは`jp.cha84rakanal.hellotogglecolor_studio_c_plusplus`にします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/876197dc-0411-5125-2a22-e8fe3c5d2426.png)

MainActivity.javaとactivity_main.xmlが自動生成されて、ディレクトリの構造は以下のようになります。

```bash:main以下の構造
main
├── AndroidManifest.xml
├── cpp
│   ├── CMakeLists.txt
│   └── main.cpp
├── java
│   └── jp
│       └── cha84rakanal
│           └── hellotogglecolor_studio_c_plusplus
│               └── MainActivity.java
└── res
    ├── layout
    │   └── activity_main.xml
    ├── mipmap-hdpi
    │   └── ic_launcher.png
    ├── mipmap-mdpi
    │   └── ic_launcher.png
    ├── mipmap-xhdpi
    │   └── ic_launcher.png
    ├── mipmap-xxhdpi
    │   └── ic_launcher.png
    └── values
        └── strings.xml
```

自動生成されてMainActivity.javaはAppCompatActivityクラスを継承していますが、C++のActivityと共存させるために`NativeActivity`クラスを継承します。 MainActivity.javaの内容は次のようにして、アプリが起動したらログに`in onCreate`と出るようにします。

```java:MainActivity.java
package jp.cha84rakanal.hellotogglecolor_studio_c_plusplus;

import android.app.NativeActivity;
import android.os.Bundle;
import android.util.Log;

public class MainActivity extends NativeActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.v("java_code","in onCreate");
    }

}
```

このままでは、MainActivity.javaが起動しないので、`AndroidManifest.xml`を編集しておきます。`application`要素の`android:hasCode="false"`を消して、`activity`要素の`android:name`を先程作成したActivityの名前にします。

```xml:AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<!-- BEGIN_INCLUDE(manifest) -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="jp.cha84rakanal.hellotogglecolor_studio_c_plusplus"
          android:versionCode="1"
          android:versionName="1.0">

<!-- This .apk has no Java code itself, so set hasCode to false. -->
<application
    android:allowBackup="false"
    android:fullBackupContent="false"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name">
    <!-- Our activity is the built-in NativeActivity framework class.
        This will take care of integrating with our NDK code. -->
    <activity android:name=".MainActivity"
              android:label="@string/app_name"
              android:configChanges="orientation|keyboardHidden">
            <!-- Tell NativeActivity the name of our .so -->
            <meta-data android:name="android.app.lib_name"
                android:value="native-activity" />
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
<!-- END_INCLUDE(manifest) -->
```

これでアプリをビルド/RUNするとC++で作成したmain.cppとJavaで作成したMainActivity.javaが起動していることを確認できると思います。

次は、XMLで定義したViewを表示していけるようにします。サンプルをみると、`onCreate`では`setContentView`をしておらず、`showUI`というメソッドでUIを表示しているみたいです。なのでまずは`MainActivity`に`showUI`メソッドを実装します。

```java:MainActivity.java
    MainActivity activity;
    PopupWindow popupWindow;

    // Our popup window, you will call it from your C/C++ code later
    @SuppressLint("InflateParams")
    public void showUI() {

        Log.v("java_code","showui Called");

        if( popupWindow != null )
            return;

        activity = this;

        this.runOnUiThread(()->{

            LayoutInflater layoutInflater
                    = (LayoutInflater)getBaseContext()
                    .getSystemService(LAYOUT_INFLATER_SERVICE);
            View popupView = layoutInflater.inflate(R.layout.activity_main, null);

            popupWindow = new PopupWindow(
                    popupView,
                    WindowManager.LayoutParams.WRAP_CONTENT,
                    WindowManager.LayoutParams.WRAP_CONTENT);

            LinearLayout mainLayout = new LinearLayout(activity);
            ViewGroup.MarginLayoutParams params = new ViewGroup.MarginLayoutParams(WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT);
            params.setMargins(0, 0, 0, 0);

            activity.setContentView(mainLayout, params);

            // Show our UI over NativeActivity window
            popupWindow.showAtLocation(mainLayout, Gravity.CENTER, 0, 0);
            popupWindow.update();

        });

    }
```
`layoutInflater.inflate`で`R.layout.activity_main`をしているので、`activity_main.xml`を次のように変更しておきます

```xml:activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<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"
    tools:context=".MainActivity">

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

</RelativeLayout>
```

これで、ビルド/RUNで画面の真ん中に`Hello World!!`と表示されるわけではありません。`showUI`メソッドがどこからも呼び出されていません。じゃあどこから呼び出すのかというとC++で実装しているNativeActivity`main.cpp`から呼び出します。 `main.cpp`に次の関数を加えます。実行中のVMにアタッチして、showUIをC++側から呼び出せるようにします。

```c++:main.cpp
void showUI(struct engine* engine) {
    JNIEnv* jni;
    engine->app->activity->vm->AttachCurrentThread(&jni, NULL);

    // Default class retrieval
    jclass clazz = jni->GetObjectClass(engine->app->activity->clazz);
    jmethodID methodID = jni->GetMethodID(clazz, "showUI", "()V");
    jni->CallVoidMethod(engine->app->activity->clazz, methodID);

    engine->app->activity->vm->DetachCurrentThread();
    return;
}
```

そして、`engine_init_display(struct engine* engine)`の一番最後で、加えた`showUI(struct engine* engine)`を呼び出します。

```c++:main.cpp
/**
 * Initialize an EGL context for the current display.
 */
static int engine_init_display(struct engine* engine) {
    // initialize OpenGL ES and EGL

    //-----省略-----//
    
    // Initialize GL state.
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
    glEnable(GL_CULL_FACE);
    glShadeModel(GL_SMOOTH);
    glDisable(GL_DEPTH_TEST);

    ShowUI(engine); //<--さっき追加した関数

    return 0;
}
```

これで、NativeActivityでの画面の初期化が終わったあとに、Java側でViewをオーバーレイして表示します。

![output2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/fbcda22e-502c-d9a7-2e5a-ecf2ddcc7b8e.gif)

これで、背景はC++でUIがJavaの状態で画面中央に`Hello World`と表示されました！
ここまで来るとボタンの設置は簡単です。`activity_main.xml`を次のように変更するだけでボタンを実装できます。

```xml:activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<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"
    tools:context=".MainActivity">

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

</RelativeLayout>
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/cb294bee-9815-7a3d-48c4-e4a00ae687d5.png)

### ボタンがクリックしたことを検知
Java側でボタンがクリックされたことを検知することは簡単ですね。ボタンに`button`とIDをふっているので、`setOnClickListener`メソッドを使っておしまいです。

```java:MainActivity.java
popupView.findViewById(R.id.button).setOnClickListener(v -> {
        Log.e("java_code","ButtonClicked Called");
});
```
Java側では検知できましたが、C++側は何もわかりません。背景の描画を担当しているのは、C++側なので、JavaからC++の関数を叩いて上げる必要があります。

まず`main.cpp`にJavaから呼ばれる関数を作成します。命名規則は `Java_{Package Name}_{呼び出し元クラス名}_{メソッド名}` です。引数や戻り値などついてもろもろありますがここでは説明ません。詳しいことは`android jni`とかでググってください。 `main.cpp` に次のような関数を追加します。

```c++:main.cpp
extern "C"
JNIEXPORT void JNICALL
Java_jp_cha84rakanal_hellotogglecolor_1studio_1c_1plusplus_MainActivity_toggle(JNIEnv * env, jobject obj){
    LOGW("called in native");
}
```

次に、MainActivityから呼び出せるようにします。`System.loadLibrary`メソッドの引数に、`native-activity`を指定して、Java側でC++の関数を使えるようにロードします。あとは、C++に実装した関数を、 `public native {戻り値の型} {関数名}();` のようにJavaで定義します。そうすることで、Javaメソッドのように普通にC++の関数を呼び出せます。

```java:MainActivity.java
public class MainActivity extends NativeActivity {

    MainActivity activity;
    PopupWindow popupWindow;

    static {
        System.loadLibrary("native-activity");
    }
    public native void toggle();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.v("java_code","in onCreate");
    }

    //----省略----//
            popupView.findViewById(R.id.button).setOnClickListener(v -> {
                Log.e("java_code","ButtonClicked Called");
                toggle();
            });
    //----省略----//

```

これで、ボタンをを押すと、Java側で、`ButtonClicked Called`とログが出力され、C++で`called in native` とログが出力されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/8aebdccb-2ba4-c1c0-d4b1-15820ab8c769.png)

これで、C++でもボタンがクリックされたことわかりました。

### 背景の色を変更
背景の描画は`main.cpp`の`engine_draw_frame(struct engine* engine)`で行われています。実装をみると、EGL/OpenGLESを使って描画されているのがわかります。とすると、単に背景を塗りつぶすだけなら`glClearColor`で良さそうです。なので`main.cpp`を次のように変更していきます。

```c++:main.cpp

static int toggle_count = 0;

extern "C"
JNIEXPORT void JNICALL
Java_jp_cha84rakanal_hellotogglecolor_1studio_1c_1plusplus_MainActivity_toggle(JNIEnv * env, jobject obj){
    LOGW("called in native");
    toggle_count++;
}

/**
 * Just the current frame in the display.
 */
static void engine_draw_frame(struct engine* engine) {
    if (engine->display == NULL) {
        // No display.
        return;
    }

    if(toggle_count%2 == 0){
        // Just fill the screen with a color.
        glClearColor(1,0,0,1);
    }else{
        glClearColor(0,0,1,1);
    }


    glClear(GL_COLOR_BUFFER_BIT);

    eglSwapBuffers(engine->display, engine->surface);
}
```

※`engine.animating`が1じゃないと`engine_draw_frame(struct engine* engine)`が呼ばれないので注意

![output3.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/0872d0d6-f8d3-0e5d-c4ea-c1db9ccf4f13.gif)

とりあえずこれで`C++`??でも同じアプリができました！
Nativeで動いてるとなんだかよくわからんけど速いって気持ちになっていいですね。Android NDKも色々できることがあるので今後まとめて行けたらと思います。

# Unity
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/b7799c58-7350-59b7-cd2b-97de3588bffb.png)

- ゲーム開発エンジン
- クロスプラットフォームの開発が可能
- アセットと呼ばれる素材やツールが便利
- プラグインという形でOS固有のAPIを呼び出すことも可能

それでは、Unityを使ってAndroidアプリの作成をおこなっていきます！

0. Unity Editor/Unity Hubのインストール(説明は割愛します。 `Android Build Support` を入れるのを忘れずに)
1. Unity Hubが便利なので、Unity Hubを開いて新規作成を押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/e2f2fed9-d184-cbc5-1465-71c53472fcc2.png)

2. 今回は3Dゲームとかを作るわけでは無いので、`2D`を選択して、必要な情報を入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/694ca394-4ec0-62c9-c47c-bdc4a6d5d2b5.png)

これでUnity Editorの画面が表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/35c14534-b757-3aa7-8b87-8e1890c9096b.png)

兎にも角にもこの状態でAndroid上で動かして、エラーとか起こらないことを確認しましょう。
`File > Build Settings`を開くと、 `PC Mac & Linux Standalone` にUnityマークがあるので、Androidを選択して`Switch Platform` を押します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/69ea45dc-4cdd-56af-b693-e8c260937dec.png)

そうすると `Android` にUnityマークがついて、`Build and Run`を押せるので押します。ファイルダイアログが出るので、適当に`Build` ディレクトリを作って`Save` を押します。そうすると、Unity内部でビルドがはしってAPKが生成され自動でインストールされ実行されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/983d1335-7671-277e-f675-cf62202f3a62.png)

Unityのロゴが表示されて、何もない暗いブルーが表示されます。

![output4.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/f055e995-1cd4-d3dd-69f8-b2a11ab0f916.gif)

### ボタンを実装
それでは、ボタンを実装していきます。Unityではシーンにコンポーネントを設置して、ゲームやアプリを作っていきます。
`Hierarchy`ウィンドウで右クリックを押して`UI > Button`をクリックでボタンが設置されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/df8e93da-38d1-1895-7dc6-b9fa4c718fef.png)

これで`Build and Run`をするとなんとなく中央から左下に向かう途中あたりにボタンが来ます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/c26ac9f9-9b4e-0d51-27c9-a5051621d8ee.png)

位置を真ん中にして押しやすいようにもうちょっと大きくしようと思います。
`Hierarchy`に表示されている`Canvas`をクリックすると右側の`Inspector`に、Canvasに設定されてるコンポーネントの情報が表示されます。
`Canvas Scaler (Script)`という項目があるので、そこの設定を以下のようにしましょう。これで、横幅を基準に横1080x縦1920の領域として画面がレンダリングされます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/f0b5fb1b-f858-9412-bac8-76c8adb3228c.png)

Unity EditorのGameウィンドウで確認すると、アスペクト比や位置を維持していますね。
![output5.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/52480842-9157-6c8f-39e6-5f64a15c54ab.gif)

次は、`Hierarchy`に表示されている`Canvas > Button`をクリックすると右側の`Inspector`に、Buttonに設定されてるコンポーネントの情報が表示されます。
`Rect Transform`という項目があるので、そこの設定を以下のようにしましょう。これでボタンが中心に位置して大きくなります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/c68fbdd3-ba32-188e-cb75-40c0669ff045.png)

文字もよしなに大きくするとAndroid上でこんな感じになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/02a453c0-2477-bd7f-e44d-dde22dc42e5b.png)

ボタンの実装はこれで良さそうです。

### ボタンがクリックしたことを検知
次は、ボタンイベントを取得しましょう。`Assets > Create > C# Script`でC#ファイルをUntiyプロジェクトに作成します。名前は今回は`ButtonClick`としました。 `Start()` メソッドはUnityのロジックから呼ばれるものでシーンの1番最初に呼ばれます。`Update()`メソッドもUnityのロジックから呼ばれるものでシーンの描画の際毎回呼ばれます。このクラスにボタンが押されたら呼ばれるメソッドを実装します。メソッド名は適当に、`onClick`にして、呼ばれたらログを出すようにしておきます。

```c#:ButtonClick.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ButtonClick : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        
    }

    public void onClick(){
        Debug.Log("On Click");
    }
}
```

この作成した`ButtonClick`クラスをインスタンス化できるように、GameObjectにアタッチしようと思います。
`Hierarchy`ウィンドウで右クリックを押して`Create Empty`をクリックでGameObjectが設置されます。この設置されたGameObjectをクリックすると、右側の`Inspector`には`Transform`だけが表示されていると思います。`GameObject`に`ButtonClick`クラスをアタッチするのは簡単で、先ほど作成したC#Scriptを`Inspector`ウィンドウにドラッグアンドドロップするだけです。(Add Componentからもアタッチできます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/558555f7-daf6-c487-957d-dbd5b2191364.png)

GameObjectへのアタッチを終えたら、次はButtonから`onClick()`呼べるようにします。`Hierarchy`ウィンドウにあるButtonのInspectorを開きます。`Button (Script)`の項目に`On Click()`があり、そこは、`List is Empty`になってると思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/1c2d1c82-0782-dd26-dee4-e7e647d1a943.png)

`On Click()`についている`+`マークを押すと、このようにListに要素が追加されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/62b76346-61fa-3ddd-180b-036739dbeb9f.png)

`Hierarchy`ウィンドウにある先ほど作成した`GameObject`を`On Click()`のListにある`None (Object)`に向かってドラッグアンドドロップすると、次のようになり、Buttonが`ButtonClick`クラスのメソッドにアクセスできる状態になります
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/4e211bc9-e0aa-fca9-fbfd-262b12d9db74.png)

`No Function`となっているところをクリックすると、リストがドロップダウンするので、先ほどGameObjectにアタッチしたクラスと、呼びたいメソッドを指定できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/575afff9-b563-ee08-edfd-ef43f1aaac7d.png)

これでボタンを押すと、ログと`On Click`表示されます。実際のUnity Editor上で確認するとこんな感じです。
![output6.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/69635ee1-049c-74e3-f5bd-7d06c167bb3a.gif)

### 背景の色を変更
あとは、背景を色で塗りつぶすだけです。`Hierarchy`ウィンドウで右クリックを押して`UI > Panel`をクリックで、画面を覆う1枚のパネルが設置されます。Unityの`Hierarchy`は上の方が奥側なので、`Panel`を`Button`より上にします。設置した`Panel`の`Inspector`を開くと、`Image (Script)`に`Color`の項目があるので、これをいじるとパネルの色が変わります。
![output7.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/adae3f6d-c4d8-8baf-04a3-799f917b5690.gif)

このパネルの色を`onClick()`メソッド内で変えることができると良さそうですね。色を変えられるように`ButtonClick.cs`を次のように変更します。このスクリプトのこの状態では、`Imageクラスのimg`が`Null`なような気がします。実際、このままでは`Null`なので、Unity Editor上で`Imageクラスのimg`にオブジェクトを代入?アタッチ?します。

```c#:ButtonClick.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class ButtonClick : MonoBehaviour
{

    public Image img;
    private bool toggle = false;

    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        
    }

    public void onClick(){
        Debug.Log("On Click");
        img.color = (toggle)? Color.red : Color.blue;
        toggle = !toggle;
    }
}

```

`GameObject`の`Inspector`を開いてみると、`ButtonClick (Script)`の`img`の項目が`None (Image)`になっています。`None (Image)`の右側のターゲットマークをクリックするとImageをアタッチしているGameObjectの一覧が表示されるので、Pnaelを選択します。するとimgにPanelにアタッチされたImageが代入?アタッチ?されます。
![output8.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/e46b0569-e897-f67d-11d2-6a5a9a7f36c8.gif)

これで背景色を変えられるようになったので、アプリは完成です!
![output9.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/4aae6d17-b6a2-67c5-c732-cfd2358b0cdd.gif)

(4つも同じアプリを作ってかつまとめると疲れてきますね...

# Processing
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/317a31b1-5691-e2ff-3bcc-666ba2fab19f.png)

- クリエイティブコーディングのためのツール
- エンジニアではない人でも簡単に扱える
- ライブラリが様々あって便利
- 言語はJavaで描画をうまくWrapしてくれている

傾向を変えてアAndroidアプリ開発としてはマイナーな`Processing`でアプリを作って行きます。

1. Processingをインストールします。公式の[ダウンロードページ](https://processing.org/download/)からダウンロードしてZIPを解凍するだけです。
2. Processingを起動すると、IDEが立ち上がってすぐにコーディングを開始できます。デフォルトでは`Java`モードなので、PC上でプログラムが動作します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/b239f70a-9288-e3f9-69cd-c81f4e174df9.png)
3. IDE右上の`Java ▼`とあるところをクリックすると`モードの追加...`とあるのでクリックします。すると、ライブラリマネージャーが表示されるので、`Android Mode`を選択して`Install`を押します。インストールが完了すると`status`に緑のチェックマークがつくので、ライブラリマネージャーを閉じます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/50733a28-4ab4-69d1-1b2d-2ba47793e9f3.png)

4. 閉じた後、IDE右上の`Java ▼`とあるところをクリックすると`Android`の項目が追加されているので、`Android`を押すとAndroidモードになります。

5. またまた、兎にも角にも実行してみます。 `Android > Devices >`にPCに接続しているデバイスがあることを確認したら、IDE左上の`▶マーク`を押します。すると、ビルドが走りインストールされアプリがRUNします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/af8a1083-1261-34bf-f3fd-6199ee181a03.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/bb446260-5913-8082-12df-9f504db4d6a9.png)

### ボタンを実装
Processingは描画が専門な感じなので、UIを作るとなるとライブラリが必要になります。 Processingでは[controlP5](http://www.sojamo.de/libraries/controlP5/) という、GUI作成するライブラリがあるので、これを使います。

`スケッチ > インポートライブラリ > ライブラリを追加...` でライブラリマネージャーが開くので、`ControlP5`を検索し、インストールします。`Processing`といっても基本は`Java`なので、ライブラリのインポートは `import controlP5.*;` でおしまいです。ボタンをただ置くだけならIDEに次のプログラムを書くだけです。

```java:HelloToggleColor.pde
import controlP5.*;

ControlP5 control;

void setup() {
  fullScreen();

  control = new ControlP5(this);
  control.addButton("onClick")
         .setLabel("Red_Button")
         .setPosition(50, 40)
         .setSize(100, 40)
         .setColorActive(color(0, 40))    //押したときの色
         .setColorBackground(color(255))  //通常時の色
         .setColorForeground(color(255))  //マウスを乗せた時の色
         .setColorCaptionLabel(color(0)); //テキストの色
         
}

void draw() {
  
}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/5870daaa-3fd2-69da-db1c-79776f9ced1b.png)

めちゃくちゃ小さいですが、ボタンを置くことができました。

### ボタンがクリックしたことを検知
クリックの検知は簡単で、`addButton()`の引数と同じ名前のメソッドを作成するだけで、ボタンイベントを拾うことができます。今回は`"onClick"`としているので`onClick()`メソッドを実装します。`println`メソッドを使うとProcessingのIDEのコンソールに文字を表示させられます。

```java:HelloToggleColor.pde
import controlP5.*;

ControlP5 control;
int count = 0;

void setup() {
  fullScreen();

  control = new ControlP5(this);
  control.addButton("onClick")
         .setLabel("Red_Button")
         .setPosition(50, 40)
         .setSize(100, 40)
         .setColorActive(color(0, 40))    //押したときの色
         .setColorBackground(color(255))  //通常時の色
         .setColorForeground(color(255))  //マウスを乗せた時の色
         .setColorCaptionLabel(color(0)); //テキストの色
         
}

void draw() {
  
}

void onClick(){
  println("onClick:" + count);
  count++;
}

```
![output10.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/7946a834-8704-b78f-5c8f-528ca2179b40.gif)

クリックの検知もできたので、文字もボタンも小さいのを改善します。
まずは文字を改善します。、`ツール > フォントの作成...`を開いて、好きなフォントを選びます。今回は`Helvetica`を選びました。サイズを`128`ぐらいにして、`OK`を押すとフォントファイルが生成されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/8036e24c-2713-ed95-a75c-8ca8c6040e6c.png)

フォントファイルは`loadFont`メソッドで読み込んで使います。ボタンのサイズは`setPosition(int,int)` `setSize(int,int)`を使うと改善できそうです。なので`HelloToggleColor.pde`を次のように変更します。

```java:HelloToggleColor.pde
import controlP5.*;

ControlP5 control;
int count = 0;

void setup() {
  fullScreen();
  
  PFont p = loadFont("Helvetica-128.vlw"); 
  ControlFont font = new ControlFont(p);
  
  font.setSize(32);
  
  int button_width = (int)(width*0.25);
  int button_height = (int)(height*0.08);

  control = new ControlP5(this);
  control.setFont(font);
  control.addButton("onClick")
         .setLabel("Button")
         .setSize(button_width,button_height)
         .setPosition(width/2 - button_width/2, height/2 - button_height/2)
         .setColorActive(color(0, 40))    //押したときの色
         .setColorBackground(color(255))  //通常時の色
         .setColorForeground(color(255))  //マウスを乗せた時の色
         .setColorCaptionLabel(color(0)); //テキストの色
         
}

void draw() {
  
}

void onClick(){
  println("onClick:" + count);
  count++;
}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/9a11d17a-612f-ce2f-2b1f-578f1a87da25.png)

文字のサイズ、ボタンの位置、ボタンのサイズがちょうどよくなりました。

### 背景の色を変更
`Processing`で背景を特定の色で塗りつぶすのは簡単です。`background`メソッドを使うだけなので、プログラムは次のようになります。

```java:HelloToggleColor.pde
import controlP5.*;

ControlP5 control;
int count = 0;
boolean toggle = false;

void setup() {
  fullScreen();
  background(255, 0, 0);
  
  PFont p = loadFont("Helvetica-128.vlw"); 
  ControlFont font = new ControlFont(p);
  
  font.setSize(32);
  
  int button_width = (int)(width*0.25);
  int button_height = (int)(height*0.08);

  control = new ControlP5(this);
  control.setFont(font);
  control.addButton("onClick")
         .setLabel("Button")
         .setSize(button_width,button_height)
         .setPosition(width/2 - button_width/2, height/2 - button_height/2)
         .setColorActive(color(0, 40))    //押したときの色
         .setColorBackground(color(255))  //通常時の色
         .setColorForeground(color(255))  //マウスを乗せた時の色
         .setColorCaptionLabel(color(0)); //テキストの色
         
}

void draw() {
  
}

void onClick(){
  println("onClick:" + count);
  count++;
  toggle = !toggle;
  if(toggle){
    background(0, 0,255);
  }else{
    background(255, 0, 0);
  }
}

```

![output11.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/163140ac-db2d-69d1-c8fa-d97cb1c9ac46.gif)

これで`Processing`でも完成しました。

<!--https://code.google.com/archive/p/apwidgets/-->

# openFrameworks
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/f0c37750-d068-a248-2cf8-fa9a04433de2.png)

- クリエイティブコーディングのためのツール
- エンジニアではない人でも簡単に扱える
- アドオンが豊富で便利
- C++で書かれているため速度だせる(?)

同じく、Androidアプリ開発としてはマイナーな`openFrameworks`でアプリを作ります。
この記事では `v0.11.0` の `android` 版を使います。

1. `openFrameworks`をインストールします。これも、公式のダウンロードページからダウンロードしてZIPを解凍するだけです。 今回は、mobileの行にあるAndroid版をダウンロードしてきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/1b0b1da6-8c9c-0220-0965-d7dea05a3df0.png)

2.`of_v0.11.0_android_release/projectGenerator-{OS}` ディレクトリにある`projectGenerator`を開きます。初めて開くとおそらくopenFrameworksのパスを求められるので先ほどダウンロードして展開したディレクトリを選択します。Project Nameにプロジェクトの名前、Project pathにプロジェクトの保存先を指定して、`Generate`を押すと`openFrameworks`のプロジェクトが生成されます。(念のためPlatformがAndroidになっていることを確認しておきましょう
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/256d52db-b186-41cd-697a-5d217b85e5e1.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/a8adaa2f-6c83-59d6-59da-bd7cf793a666.png)
Android Studio側で`Tools -> Create Command-line Launcher...`の設定を行っていると`Open in IDE`でAndroid Studioが開きます。

3.筆者は設定していないので手動で`Android Studio`を開き、 `Import Project (Gradle ,Eclipse ADT, etc.)` をクリックして、生成されたプロジェクトのディレクトリを選択します。Openを押すと自動でGradle Syncが走ります。(Gradle Syncが走らない場合は、手動でSyncします。
![alt](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/3c84726d-04a5-baff-dc2e-c1372b771353.png)

4.`Gradle Sync`に失敗した場合は、`build.gradle`と`settings.gradle`を修正する必要があります。スクリプトファイルでは、`openFrameworks`のパスが`../../../`になっているので正しいパスに直します。
自分の環境では`/Users/cha84rakanal/Documents/of_v0.11.0_android_release`ディレクトリに`openFrameworks`を配置しているので、そのパスに置き換えます。

```gradle:build.gradle上部
def ofRoot(){ return '/Users/cha84rakanal/Documents/of_v0.11.0_android_release/' }

// Load common functions
apply from: ofRoot()+"libs/openFrameworksCompiled/project/android/common-functions.gradle"

buildscript {
    apply from: "/Users/cha84rakanal/Documents/of_v0.11.0_android_release/libs/openFrameworksCompiled/project/android/ndk-verify.gradle"

    repositories {
        jcenter()
    }
    dependencies {
        // Using the gradle-experimental version that supports c++
        classpath 'com.android.tools.build:gradle-experimental:0.9.3'
    }
}
```

```gradle:settings.gradle上部
// openFrameworks-relative root directories (don't touch)

def ofRoot = '/Users/cha84rakanal/Documents/of_v0.11.0_android_release/'

// Load common functions
apply from: ofRoot+"libs/openFrameworksCompiled/project/android/common-functions.gradle"
```

`ERROR: Wrong version of NDK library found. Found version 19.2.5345600, but openFrameworks requires version r15c`というエラーが出た場合は、`local.properties`を編集して[Android NDK r15c](https://developer.android.com/ndk/downloads/older_releases.html?hl=ja)のインストールされてるパスを指定します。

5.`Gradle Sync`が通れば、まずは実行してみます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/83781e1c-9bf2-1248-e8e0-bcfdc942b880.png)
灰色で背景が塗りつぶされていれば正しいです。

### ボタンを実装
openFrameworksもProcessingと同様に、描画が専門な感じなので、UIを作るとなるとアドオンが必要になります。~~openFrameworksでは[ofxDatGui](https://braitsch.github.io/ofxDatGui/) という、GUI作成するアドオンがあるので、これを使います。~~ 試してみたら`ofxDatGui`を使ってできなかったので、 Android Studio + NDKで使った方法でボタンを実装していきます。(この方法はずるいなぁと思いながら...

`AndroidManifest.xml`をみると、起動するActivityが`cc.openframeworks.HelloColorToggle.OFActivity`となっているので、`srcJava/OFActivity.java`を見てみます。

```xml:AndroidManifest.xml
       <activity
            android:name="cc.openframeworks.HelloColorToggle.OFActivity"
            android:label="@string/app_name"
            android:configChanges="orientation|screenSize|screenLayout|smallestScreenSize">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
```

`OFActivity.java`にはこれといった実装はないのですが、`cc.openframeworks.OFActivity`クラスを継承しています。なので、`cc.openframeworks.OFActivity`にマウスカーソルを合わせて、右クリックして`Go To > Declaration`で定義に飛びます。
すると、`this.setContentView(view);`で、`R.layout`のXMLで定義されたViewを読み込んでいることを発見できました。

```java:cc.openframeworks.OFActivity.java
public void initView(){  
		String packageName = this.getPackageName();
        try {
        	Log.v("OF","trying to find class: "+packageName+".R$layout");
			Class<?> layout = Class.forName(packageName+".R$layout");
			View view = this.getLayoutInflater().inflate(layout.getField("main_layout").getInt(null),null);
			if(view == null) {
				Log.w("OF", "Could not find main_layout.xml.");
				throw new Exception();
			}
			this.setContentView(view);
			
			Class<?> id = Class.forName(packageName+".R$id");
			mOFGlSurfaceContainer = (ViewGroup)this.findViewById(id.getField("of_gl_surface_container").getInt(null));
			
			if(mOFGlSurfaceContainer == null) {
				Log.w("OF", "Could not find of_gl_surface_container in main_layout.xml. Copy main_layout.xml from latest empty example to fix this warning.");
				throw new Exception();
			}
			
		} catch (Exception e) {
			Log.w("OF", "couldn't create view from layout falling back to GL only",e);
			mOFGlSurfaceContainer = new FrameLayout(this);
	        this.setContentView(mOFGlSurfaceContainer);
		}
	}
```
なので、ボタンを配置するだけなら、`res/layout/main_layout.xml`で配置するだけでおしまいです。`main_layout.xml`を次のように編集するとボタンが置かれます

```xml:main_layout.xml
<?xml version="1.0" encoding="utf-8"?>
   <RelativeLayout android:id="@+id/relativeLayout1" android:layout_width="fill_parent" android:layout_height="fill_parent" xmlns:android="http://schemas.android.com/apk/res/android">
       <RelativeLayout android:id="@+id/of_gl_surface_container" android:layout_width="fill_parent" android:layout_height="fill_parent"/>
       <Button
           android:id="@+id/button"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="Button" />
       <!-- add here other views' layouts -->
    </RelativeLayout>
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/4b762777-0f89-0996-c589-2d543436fbcd.png)

<!--
まずはリポジトリから`ofxDatGui`をクローンしてきます。このとき、`/path/to/of_v0.11.0_android_release/addons`ディレクトリでクローンするとコピーの手間が省けるので楽です。

```bash:ofxDatGuiのクローン
cd /path/to/of_v0.11.0_android_release/addons
git clone https://github.com/braitsch/ofxDatGui.git ofxDatGui
```
cloneが終わればインストールはおしまいなので、プロジェクトにアドオンを追加します。
`projectGenerator`を開いて、`Import` ボタンを開いて先ほど作成したプロジェクトのディレクトリを選択します。Addonsの項目のドロップダウンリストを開くと、プロジェクトに追加できるアドオンの一覧が表示されるので、`ofxDatGui`をクリックして追加します。(ofxGuiというのもありますが今回は使いません)。Addonsに`ofxDatGui`が表示されたら`Update`を押します。すると、プロジェクトに`ofxDatGui`が追加されます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/b7cfa671-116e-153b-dd43-331eb4db0e56.png)

openFrameworksでは基本的に、`src/ofApp.h`と`src/ofApp.cpp`を編集して開発していきます。
ボタンを設置するために、`src/ofApp.h` で `#include "ofxDatGui.h"`を加えます。

```c++:ofApp.h
#pragma once

#include "ofMain.h"
#include "ofxAndroid.h"
#include "ofxDatGui.h" // <---- 追加

class ofApp : public ofxAndroidApp{
	
	public:
//----省略----//
```
-->

### ボタンがクリックしたことを検知
次は、ボタンがクリックしたことを検知します。親クラスで`setContentView()`したViewに子クラスでもアクセスできるので`srcJava/OFActivity.java`でボタンにOnClickListenerを実装します。(普通に親のabstructクラスに実装はするのはよくないし...
サクッと`findViewById()`メソッドをつかって`setOnClickListener()`メソッドで`OnClickListener`当てます。これで、ボタンをクリックするとログに`onClick`と表示されます。

```java:OFActivity.java
public class OFActivity extends cc.openframeworks.OFActivity{

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Log.e("of","onClick");
            }
        });
    }
```

今回も描画自体は、C++側で実装されているので、JNIを使ってC++側にボタンがクリックされたことを伝えて行きます。
まずは、C++側にJavaから呼び出せる関数を実装します。`src/ofApp.h`に`#include <jni.h>`を加えます。

```c++:ofApp.h
#pragma once

#include "ofMain.h"
#include "ofxAndroid.h" 
#include <jni.h> // <---- 追加

class ofApp : public ofxAndroidApp{
	
	public:
//----省略----//
```

次に、実際に呼び出す関数を`src/ofApp.cpp`に実装します。今回は`click`というメソッド名で呼び出せるようにします。命名規則通りの関数名は次のようになります。

```c++:ofApp.h
#include "ofApp.h"

extern "C"
JNIEXPORT void JNICALL
Java_cc_openframeworks_HelloColorToggle_OFActivity_click(JNIEnv* env,jobject thiz){
    ofBackground(255,255,255);
}

//--------------------------------------------------------------
void ofApp::setup(){

}
```

**あんまり良くないTipsですが、** C++でつける関数名がわからない場合は、`C++`で何も実装せずに`Java側`で`public native {戻り値の型} {関数名}(引数...);`とメソッド名だけ定義して適当なところで呼び出す形で実行します。アプリが`UnsatisfiedLinkError`をだして、本来呼べたはずの関数名をログに出力するので、それを使います。下の場合だと`hoge()`というメソッド名で関数を作成したい場合は`Java_cc_openframeworks_HelloColorToggle_OFActivity_hoge`という関数名でC++側で実装するべきたとわかります。

```bash:UnsatisfiedLinkError
2019-12-03 12:18:09.617 17648-17648/cc.openframeworks.HelloColorToggle E/AndroidRuntime: FATAL EXCEPTION: main
    Process: cc.openframeworks.HelloColorToggle, PID: 17648
    java.lang.UnsatisfiedLinkError: No implementation found for void cc.openframeworks.HelloColorToggle.OFActivity.hoge() (tried Java_cc_openframeworks_HelloColorToggle_OFActivity_hoge and Java_cc_openframeworks_HelloColorToggle_OFActivity_hoge__)
        at cc.openframeworks.HelloColorToggle.OFActivity.hoge(Native Method)
        at cc.openframeworks.HelloColorToggle.OFActivity$1.onClick(OFActivity.java:27)
        at android.view.View.performClick(View.java:6294)
        at android.view.View$PerformClick.run(View.java:24770)
        at android.os.Handler.handleCallback(Handler.java:790)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:164)
        at android.app.ActivityThread.main(ActivityThread.java:6494)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
```

`OFActivity.java`を次のように編集すると、ボタンをクリックすると背景が白く塗りつぶされるアプリが完成します。

```java:OFActivity.java
public class OFActivity extends cc.openframeworks.OFActivity{

    public native void click();

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                click();
            }
        });
    }
```

![output12.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/7e8ddc84-d1ca-3e74-2f90-fe82a03fbb7d.gif)


### 背景の色を変更
ボタンのクリックでもうやってしまいましたが、背景色を変えるのは、`ofBackground(int 0-255,int 0-255,int 0-255);`ですね。`openFrameworks`の構造は`ofApp::setup()`はアプリが立ち上がった後の1回のみ呼ばれて、画面描画ごとに`ofApp::update()` `ofApp::draw()` が呼ばれます。それを踏まえて、`ofApp.cpp`を次のように編集します。

```c++:ofApp.cpp
#include "ofApp.h"

static bool toggle;

extern "C"
JNIEXPORT void JNICALL
Java_cc_openframeworks_HelloColorToggle_OFActivity_click(JNIEnv* env,jobject thiz){
    toggle = !toggle;
}

//--------------------------------------------------------------
void ofApp::setup(){
    toggle = true;
    ofBackground(255,0,0);
}

//--------------------------------------------------------------
void ofApp::update(){

}

//--------------------------------------------------------------
void ofApp::draw(){
    if(toggle)
        ofBackground(255,0,0);
    else
        ofBackground(0,0,255);
}
```

ボタンは`main_layout.xml`のボタン要素に`android:layout_centerInParent="true"`を加えるだけで真ん中にきます。
![output13.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/a4b8ac2e-eebb-2fd3-ca53-092bb41ce515.gif)


# Cordova
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/22cd7e95-dfef-ecb6-77f1-edd46360f7fa.png)

- 簡単にクロスプラットフォーム
- HTML/JS/CSSが分かれば、アプリを作れる
- Webの資産を使い回せる

今度は、Nativeから離れて、WebViewを元に作られているCordovaというフレームワークを使ってアプリを作ります。

1.Cordovaをインストールします。`npm`が入っていることが前提です。ターミナルに次のコマンドを打ち込むだけでインストールは終わりです。

```bash:cardovaのインストール
$npm install -g cordova
```

2.アプリのプロジェクトを作成します。事前にアプリのプロジェクトを生成するディレクトリへ移動しておきます。

```bash:HelloToggleColorというアプリ名でcordovaのプロジェクトを作成
$cordova create HelloToggleColor
```

プロジェクトディレクトリを見てみると、`index.html` や `index.js` が見受けられるので、どうやらこれらを編集して開発をすすめていけば良さそうな気がします。

```bash:プロジェクトのディレクトリ構成
HelloToggleColor
├── config.xml
├── hooks
│   └── README.md
├── package.json
├── platforms
├── plugins
└── www
    ├── css
    │   └── index.css
    ├── img
    │   └── logo.png
    ├── index.html
    └── js
        └── index.js
```

3.プロジェクトディレクトリに移動して、Platformを追加します。今回は、Androidアプリなので`android`を追加します。

```bash:androidをプラットフォームとして追加
$cd HelloToggleColor
$cordova platform add android
```

4.アプリを起動します。実機をつないでいれば自動でインストールされた立ち上がります。

```bash:アプリのビルドと実行
$cordova run android
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/a80dc261-3ea2-ab56-a48c-8a5b8b3bd86f.png)

え、やば、簡単すぎんか...？

`$adb shell dumpsys activity top`を使うとViewの構成とかが見れます。なので、Cordovaアプリがどうなっているかというと、`SystemWebView` で構成されていることがわかります。

```bash:dumpsysでViewHierarchyの確認
TASK io.cordova.hellocordova id=140 userId=0
  ACTIVITY io.cordova.hellocordova/.MainActivity 17398e4 pid=24311      
    View Hierarchy:
      DecorView@8e127c8[MainActivity]
        android.widget.LinearLayout{ead1061 V.E...... ........ 0,0-1080,1794}
          android.view.ViewStub{6b3b786 G.E...... ......I. 0,0-0,0 #1020187 android:id/action_mode_bar_stub}
          android.widget.FrameLayout{4142847 V.E...... ........ 0,63-1080,1794 #1020002 android:id/content}
            org.apache.cordova.engine.SystemWebView{ec4f874 VFEDH.C.. .F...... 0,0-1080,1731 #64}
        android.view.View{b49519d V.ED..... ........ 0,1794-1080,1920 #1020030 android:id/navigationBarBackground}
        android.view.View{183c612 V.ED..... ........ 0,0-1080,63 #102002f android:id/statusBarBackground}
```

ここからの気持ちはAndroidアプリ開発ではなくモバイルWeb開発なのか...と思いながら目的のアプリを作っていきます。
### ボタンを実装
`HTML`なら `<button>`タグを追加するだけでbuttonを置けます...

```html:index.js
<body>
   <button type=button>Button</button>
   <script type="text/javascript" src="cordova.js"></script>
   <script type="text/javascript" src="js/index.js"></script>
</body>
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/3de2a0ab-1882-e743-37e9-28e7b61b305e.png)

Androidなのに味気が無いので、マテリアルデザインっぽいボタンしていきます。
今はサポートされて無いですが、ボタンだけなら扱いやすいので、[Material Design Lite](https://getmdl.io/index.html)を導入します。プロジェクトのディレクトリに移動して次のコマンドを実行してローカルに落としてきます。

```bash:MaterialDesignLiteのダウンロード
$npm install material-design-lite --save
```

CordovaのHTMLからは、基本的には、`path/to/project/www`のフォルダしかアクセスできないようなので、./node_modules/から ./wwwへcssとjsファイルをコピーします。

```bash:
cp ./node_modules/material-design-lite/material.min.css ./www/css/
cp ./node_modules/material-design-lite/material.min.js ./www/js/
```

あとは、ヘッダーに次のコードを追加して、HTMLでの読み込みは完了です。

```html:index.html
<link rel="stylesheet" href="./css/material.min.css">
<script src="./js/material.min.js"></script>
```
ボタンを中央に置きたいので `index.css` に次のコードを追加して、`index.html`のButton要素を囲います。

```css:index.css
.wrap2 {
    width: 100%;
    height: 100%;
    display: flex;
    justify-content: center;
    align-items: center;
}
```

```html:index.html
<div class="wrap2">
    <button class="mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect">
        Button
    </button>
</div>
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/dec89aa4-e50b-0198-58d9-6a36a901e887.png)

NativeのUIとほとんど変わらないように見えます

### ボタンがクリックしたことを検知
これも楽ですね。`Button`タグにonClickプロパティをつけるか、Javascriptで`addEventListener`を使うかです。
今回はJavascriptを書きます。`js/index.js`を開いてコードをサクッと実装します。ここでの`console.log()`は、Google ChromeのInspectorにログを出力できます。GoogleChromeのアドレスバーに`chrome://inspect/`と入力してページを開き、端末の`inspect`を押すと、実行中の画面とともに、consoleが表示されます。

```javascript:index.js
var app = {
    // Application Constructor
    initialize: function() {
        document.addEventListener('deviceready', this.onDeviceReady.bind(this), false);

        document.getElementById('button1').addEventListener('click',()=>{
            console.log('click');
        });
    },
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/fe2fc20f-8a83-8e92-9601-846385033024.png)

### 背景の色を変更
あとは背景の色を変えるだけです。CSSのbackgtoundプロパティをいじっていきます。`js/index.js`を開いてコードを加えます。

```javascript:index.js
var app = {

    toggle: false,

    // Application Constructor
    initialize: function() {
        document.addEventListener('deviceready', this.onDeviceReady.bind(this), false);

        document.getElementById('back').style.background = 'red';
        document.getElementById('button1').addEventListener('click',()=>{

            document.getElementById('back').style.background = (this.toggle)? 'red' : 'blue';
            this.toggle = !this.toggle;
            console.log('click');

        });
    },
```

ボタンに設定されているアルファ値が低いので後ろの色が反映されてしまいましたが`Cordova`でも同じアプリができました。

![output14.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/bbb4266b-0892-cb34-c0c1-515f4e3ae9b0.gif)

# React Native
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/83959734-5456-d047-a88c-e053ea86daac.png)

[Getting Started](https://facebook.github.io/react-native/docs/getting-started)のページに行くと、React Nativeの開発ツールとして`Expo CLI`を使うのと`React Native CLI`を使うのとがある。
まずは、`Expo CLI` から試してみることにする。

1.まず、`Expo CLI`をインストール。

```bash:ExpoCLIのインストール
$npm install -g expo-cli
```
2.プロジェクトを作るディレクトリに移動して、プロジェクトを生成

```bash:プロジェクトを作成
$expo init HelloToggleColor
```
Node.jsのバージョンはサポートしているものに上げる必要がある。

```bash:Node.js10.8.0には対応していない....
ERROR: Node.js version 10.8.0 is no longer supported.

expo-cli supports following Node.js versions:
* >=8.9.0 <9.0.0 (Maintenance LTS)
* >=10.13.0 <11.0.0 (Active LTS)
* >=12.0.0 (Current Release)
```

3.どのテンプレートで作成するか聞かれるので、`blank`を選びます。

```bash:テンプレートの選択
? Choose a template: (Use arrow keys)
  ----- Managed workflow -----
❯ blank                 a minimal app as clean as an empty canvas 
  blank (TypeScript)    same as blank but with TypeScript configuration 
  tabs                  several example screens and tabs using react-navigation 
  ----- Bare workflow -----
  minimal               bare and minimal, just the essentials to get you started 
  minimal (TypeScript)  same as minimal but with TypeScript configuration 
```

4.プロジェクトが生成されたら、まずは端末で実行します。プロジェクトのディレクトリに移動して、`npm start` します。

```bash:アプリの起動
cd HelloToggleColor
npm start
```

すると、サーバーが立ち上がり、ブラウザに開発ツール、ターミナルにQRコードが表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/78b03832-e7ff-b1bc-54e7-4199d79a4241.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/74c5b921-7119-e776-994f-02402221dcc7.png)

5.実行する端末で [Expo](https://play.google.com/store/apps/details?id=host.exp.exponent&hl=ja) というアプリをインストールしておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/656caaf8-6cbc-116f-28d1-6913a312d6ea.png)

6.インストールされたExpoアプリでQRコードをScanすると、JavaScriptをバンドルして、アプリが表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/2dc22d16-00c8-78ff-9266-9d6303ec6a67.png)

ターミナルでは次のコマンドが使えるので、`a` を押すとターミナルからアプリを起動できます。

```
 › Press a to run on Android device/emulator, or i to run on iOS simulator, or w to run on web.
 › Press c to show info on connecting new devices.
 › Press d to open DevTools in the default web browser.
 › Press shift-d to disable automatically opening DevTools at startup.
 › Press e to send an app link with email.
 › Press p to toggle production mode. (current mode: development)
 › Press r to restart bundler, or shift-r to restart and clear cache.
 › Press s to sign in.
```

### ボタンを実装
それでは、ボタンを実装していきます。アプリのメインが画面を作成しているところは `App.js`なので、これを編集していきます。
`HTML`のノリで `<button>` ダグを置いてみます。

```javascript:App.js
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';

export default function App() {
  return (
    <View style={styles.container}>
      <Text>Open up App.js to start working on your app!</Text>
      <button><Text>Button</Text></button>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
});

```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/de24107d-d0e5-8aa0-ced0-adf3fd608c46.png)
だめでした。

よくわからないときは公式ドキュメントを見てみます。公式ドキュメントの[ボタン](https://facebook.github.io/react-native/docs/button)の項目のサンプルコードを参考に書き直します。

```javascript:App.js
import React from 'react';
import { StyleSheet, Text, Button,View } from 'react-native';

export default function App() {
  return (
    <View style={styles.container}>
      <Button
          onPress={this.onPressLearnMore}
          title="Learn More"
          color="#858585"
          accessibilityLabel="Learn more about this purple button"
      />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
});
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/b3234f16-61e7-9426-38a0-f5e1d8e61c8d.png)

なんとかボタンが表示されました。

### ボタンがクリックしたことを検知
ボタンが押されたらonPressにセットしたメソッドが呼ばれるのでメソッドを実装します。

```javascript:App.js
import React from 'react';
import { StyleSheet, Text, Button, View, Alert} from 'react-native';

export default function App() {

  onPressLearnMore = ()=>{
    Alert.alert('pressed button')
  };

  return (
    <View style={styles.container}>
      <Button
          onPress={this.onPressLearnMore}
          title="Learn More"
          color="#858585"
          accessibilityLabel="Learn more about this purple button"
      />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
});

```

ボタンを押したらダイアログが表示されるようにしました。

![output15.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/f53e78b8-d833-4793-4cc1-782af5483d87.gif)

### 背景の色を変更
背景の色を変えます。画面いっぱいに構成されている`View`コンポーネントのスタイルを変更するのが良さそうです。まずは、styleに背景が赤になるスタイルと青になるスタイルを加えます。

```javascript:App.js
const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
  red: {
    flex: 1,
    backgroundColor: '#f00',
    alignItems: 'center',
    justifyContent: 'center',
  },
  blue: {
    flex: 1,
    backgroundColor: '#00f',
    alignItems: 'center',
    justifyContent: 'center',
  },
});
```

ボタンが押されたら、`setState`を呼び出して、Viewに割り当てるスタイルを変えます。さっきは、`export default fuction`でしたが、`export default class`に変えておきます。

```javascript:App.js
export default class App extends React.Component{

  constructor(props) {
    super(props);
    this.state = {
      styleVal : styles.container,
      toggle : true
    }
  }

  onPressLearnMore = () => {
    this.setState(
      {
        styleVal : (this.state.toggle)?styles.red : styles.blue,
        toggle : !this.state.toggle
      }
    );
  }

  render = () => {
    return (
      <View style={this.state.styleVal}>
        <Button
            onPress={this.onPressLearnMore}
            title="Learn More"
            color="#858585"
            accessibilityLabel="Learn more about this purple button"
        />
      </View>
    );
  }

};
```

![output16.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/534f409d-d5e1-7283-6be3-e8b64cafd5c1.gif)

これでなんとか`React Native`でもできました！

# Visual Studio

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/31d20806-a1e5-0199-02d8-7b030c9235bb.png)

まずはインストールから初めていきます。(Windowsの方はすみません

1.MSの[Visual Studio](https://docs.microsoft.com/ja-jp/visualstudio/mac/installation)のページにいき、インストーラーをダウンロードします。今回は、`Visual Studio for Mac`をダウンロードしてきます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/b8135706-8d6e-1217-4f4b-815f2ce10e2e.png)
2.ダウンロードしたdmgを開いてインストーラーを起動します。インストールするコンポーネントのAndroidにチェックがついていることを確認して`インストール`を押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/22d94a15-2853-f061-7b7e-adada717e992.png)
3.Visual Studioを開き、`+新規`でプロジェクトを新しくプロジェクトを作成します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/e2a108ca-a3ca-698c-e16c-846ee2e22860.png)

Visual Studioで作成できるAndroidアプリは`Xamarin.Forms`と`Xamarin.Android`があるので、まずは`Xamarin.Forms`でアプリを作っていきます。

## Xamarin.Forms
1.マルチプラットフォームで、`空白フォームのアプリ`を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/0cf5d55e-5cd9-5454-2078-edf2d83341ca.png)
2.必要な情報を入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/131b9b93-9f82-944c-9e51-3f1ff990344f.png)
3.プロジェクトの保存先などを指定して作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/202f504b-e2dc-904b-690f-d68e494bb013.png)

これで、プロジェクトが作成されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/037dde50-f1dc-b735-acc5-114ee0ca56a4.png)

とりあえず実機で実行してみます。この部分で実行するOSと端末を設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/4363fd33-1af8-7a76-553e-828c7299debb.png)

こんな感じで `Welcome to Xamarin.Forms!`と画面中央に設置されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/a2f5466d-ee73-d375-8993-37f7be39434f.png)

### ボタンを実装
まずは、ボタンを設置していきます。最初の画面は`MainPage.xmal`で構成されているので、編集していきます。
Android Studioで読み書きする`activity_main.xml`に似ていますね。<Label>要素だったところを<Button>要素に変えるだけです。IDEの右側にコンポーネントのリストがあるので実際ドラッグアンドドロップで要素を置けるの楽ですね。

```xml:MainPage.xmal
<?xml version="1.0" encoding="utf-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:d="http://xamarin.com/schemas/2014/forms/design" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" x:Class="HelloToggleColor.MainPage">
    <StackLayout>
        <!-- Place new controls here -->
        <Button Text="Button" HorizontalOptions="Center" VerticalOptions="CenterAndExpand"/>
    </StackLayout>
</ContentPage>
```

マテリアルデザインなボタンが配置されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/219b33e0-a1c8-a391-8a86-084bbdcc66c8.png)

### ボタンがクリックしたことを検知
次はボタンクリックの検知です。`MainPage.xmal`に対応して、`MainPage.xmal.cs`があるので、おそらくイベント処理的なものはここに書いて行けば良さそうです。まずはボタンをクリックしたら呼ばれる関数を実装します。C#でのログ出力は`System.Console.WriteLine`を使います。

```c#:MainPage.xmal.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;

namespace HelloToggleColor
{
    // Learn more about making custom code visible in the Xamarin.Forms previewer
    // by visiting https://aka.ms/xamarinforms-previewer
    [DesignTimeVisible(false)]
    public partial class MainPage : ContentPage
    {
        public MainPage()
        {
            InitializeComponent();
        }

        void OnButtonClicked(object sender, EventArgs args)
        {
            Console.WriteLine("DEBUG - Button Clicked!");
        }
    }
}

```

ボタンにはどの関数を呼び出せばいいかを`Clicked`プロパティにセットしておきます。

```xml:MainPage.xmal
<?xml version="1.0" encoding="utf-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:d="http://xamarin.com/schemas/2014/forms/design" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" x:Class="HelloToggleColor.MainPage">
    <StackLayout>
        <!-- Place new controls here -->
        <Button Text="Button"
                HorizontalOptions="Center"
                VerticalOptions="CenterAndExpand"
                Clicked="OnButtonClicked" />
    </StackLayout>
</ContentPage>
```

これでボタンを押すとログに`DEBUG - Button Clicked!`とでるアプリができました。
![output17.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/c8d4da34-b03d-b7bd-33fe-5df196b86cb5.gif)

### 背景の色を変更
`MainPage.xmal.cs`でロジックを書いて、`MainPage.xmal`でViewを書くことがわかったのであとは簡単です。
`MainPage.xmal.cs`から参照できるように、`MainPage.xmal`の<StackLayout>要素にNameプロパティを設定します。

```xml:MainPage.xmal
<?xml version="1.0" encoding="utf-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:d="http://xamarin.com/schemas/2014/forms/design" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" x:Class="HelloToggleColor.MainPage">
    <StackLayout x:Name="layout">
        <!-- Place new controls here -->
        <Button Text="Button"
                HorizontalOptions="Center"
                VerticalOptions="CenterAndExpand"
                Clicked="OnButtonClicked" />
    </StackLayout>
</ContentPage>
```

Nameプロパティにセットした名前で直接アクセスできるので、`BackgroundColor`プロパティに色を代入するだけでおしまい。

```c#
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;

namespace HelloToggleColor
{
    // Learn more about making custom code visible in the Xamarin.Forms previewer
    // by visiting https://aka.ms/xamarinforms-previewer
    [DesignTimeVisible(false)]
    public partial class MainPage : ContentPage
    {

        private bool toggle = true;

        public MainPage()
        {
            InitializeComponent();
        }

        void OnButtonClicked(object sender, EventArgs args)
        {
            Console.WriteLine("DEBUG - Button Clicked!");
            layout.BackgroundColor = toggle ? Color.Red : Color.Blue;
            toggle = !toggle;
        }
    }
}

```

![output18.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/89ef8b5b-b7e7-c77c-095c-b53ea04dbe08.gif)

はぇ〜、`Android Studio + C#`みたいな感じで開発しやすい。

<!-- https://qiita.com/FrogWoman/items/7a49f24a9c5480e1a246 -->

## Xamarin.Android
`Xamarin.Android`も試していきます。
1.Visual Studioを開いて、新規で`空のネイティブアプリ(iOS、Android)`を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/5b507df1-dc60-6550-66a0-ffc71c61adb4.png)
2.必要な情報を入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/7e9b840c-0d36-51b1-c025-2aa1538afb2d.png)
3.これでプロジェクトが完成しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/59b9e4a0-d2ea-9831-1e56-bf8384286cd3.png)

とりあえず、`▶`マークを押して実行します。
![output19.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/91ca9b89-35e6-31a1-d423-0b69b3eb407a.gif)

テンプレートなのに既にボタンもボタンイベントへの反応も実装されている!?

### ボタンを実装
既にボタンは実装されますが、どこでボタンが実装されているのかは確認します。この画面のレイアウトは`Resources/layout/Main.axml`に定義されています。中ををみると、普通にAndroidのレイアウトファイルになっているいます。なので、ボタンが中央にある感じに直しちゃいます。

```xml:Main.axml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button android:id="@+id/myButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="@string/hello" />

</RelativeLayout>
```

### ボタンがクリックしたことを検知
ボタンがクリックしたことを受け取るロジックは、`MainActivity.cs`に書かれています。`Java`のメソッド名のまま`C#`に持ってきた感じがすごいします。interfaceの代わりに`delegate`が使われてるのが特徴的です。

```c#:MainActivity.cs
using Android.App;
using Android.Widget;
using Android.OS;

namespace HelloToggleColor.Droid
{
    [Activity(Label = "HelloToggleColor", MainLauncher = true, Icon = "@mipmap/icon")]
    public class MainActivity : Activity
    {
        int count = 1;

        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);

            // Set our view from the "main" layout resource
            SetContentView(Resource.Layout.Main);

            // Get our button from the layout resource,
            // and attach an event to it
            Button button = FindViewById<Button>(Resource.Id.myButton);

            button.Click += delegate {
                Android.Util.Log.Info("Xamarine","onClick");
            };
        }
    }
}
```

### 背景の色を変更
`delegate`のあたりをいじって従来の`Android`開発のノリでサクッと書きます。今回はボタンの親Viewが背景の`RelativeLayout`だとわかっているので、親を取得してキャストして背景色を変えます。

```c#:MainActivity.cs
using Android.App;
using Android.Widget;
using Android.OS;

namespace HelloToggleColor.Droid
{
    [Activity(Label = "HelloToggleColor", MainLauncher = true, Icon = "@mipmap/icon")]
    public class MainActivity : Activity
    {
        private bool toggle = true;

        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);

            // Set our view from the "main" layout resource
            SetContentView(Resource.Layout.Main);

            // Get our button from the layout resource,
            // and attach an event to it
            Button button = FindViewById<Button>(Resource.Id.myButton);

            button.Click += delegate {
                Android.Util.Log.Info("Xamarine","onClick");
                ((RelativeLayout)button.Parent).SetBackgroundColor((toggle)?Android.Graphics.Color.Red : Android.Graphics.Color.Blue);
                toggle = !toggle;
            };
        }
    }
}
```

![output20.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224134/76168852-e04d-46ec-f9c2-aa5edd696c5c.gif)

`Android Studio + C#`な感じで開発しやすかった。

# 最後に
Web系の知識と、Android Studioでの開発がわかってると、色んなフレームワークをサクッと使っていける感じはありました。
今回試したフレームワークでも、普段より楽な点や面倒な点もあるので、やっぱり作るものに応じてという感じがします。
フレームワークによっては`Hello World`アプリの実行まで10分もかからないものもあるので、Eclipseを使って開発していた頃とは違うし、めちゃくちゃ敷居は低くなったと思います。なので、Androidアプリを作りたいなぁとか思ってる人は、どれかフレームワークでも選んでサクッと作り始めるのがいいです。
もうちょっとフレームワークの利点・欠点の説明とか、フレームワークの仕組みとかにも触れて話していきたいので、随時更新していくのでよろしくお願いします。