[cocos2d-x]AndroidStudioのみでNDKビルドする


# Env

- macOS 10.11.3
- cocos2d-x 3.13
- Android Studio 2.2
- Android SDK Tools 25.2.2
- Android SDK Platform-tools 24.0.3
- Android SDK Build-tools 24.0.0
- Android NDK r10e
- 404KC Android 4.4.4(実機)

前提条件としてすでにcocos2dプロジェクトを作成していること
また、AndroidSDKやNDKもインストール済みであること

SDKのインストール方法については過去記事参照

[コマンドのみでAndroid SDKをインストール](http://qiita.com/tani-shi/items/e855917eaa0387f2bc0c)

NDKは下記URLからダウンロード可能

https://dl.google.com/android/repository/android-ndk-r10e-darwin-x86_64.zip

# Step

## 1. Android Studioにcocosプロジェクトを取り込む

![スクリーンショット 2016-10-01 16.11.30.png](https://qiita-image-store.s3.amazonaws.com/0/132627/d4d43c8f-3a13-0163-34d9-2e4a95a0f8f4.png "スクリーンショット 2016-10-01 16.11.30.png")

![スクリーンショット 2016-10-01 16.17.33.png](https://qiita-image-store.s3.amazonaws.com/0/132627/443a074d-8fce-f8e4-e9ef-2cb30323f298.png "スクリーンショット 2016-10-01 16.17.33.png")

取り込んだ後gradleをビルド中にcocosが使っている
gradleがかなり古いので更新しますか？と聞いてくる

これはどっちでもいいけど、
一応最新にアップデートしてみた

![スクリーンショット 2016-10-01 16.18.55.png](https://qiita-image-store.s3.amazonaws.com/0/132627/7c1e7870-4291-257f-0b89-8c7293f000f2.png "スクリーンショット 2016-10-01 16.18.55.png")

ちなみにこんなこと聞かれたら、

![スクリーンショット 2016-10-01 16.21.25.png](https://qiita-image-store.s3.amazonaws.com/0/132627/e2643a55-ac71-b660-27f7-75b50547dacb.png "スクリーンショット 2016-10-01 16.21.25.png")

AndroidStudioとバージョン管理システムが、
連携していないということなので、連携させる

メニューの
`VCS -> Enable Version Control Integration...`
から

![スクリーンショット 2016-10-01 15.52.24.png](https://qiita-image-store.s3.amazonaws.com/0/132627/db507923-fdb6-05be-8d4b-355ca26e058b.png "スクリーンショット 2016-10-01 15.52.24.png")

Gitを選択(Gitを使用している場合)

![スクリーンショット 2016-10-01 15.53.18.png](https://qiita-image-store.s3.amazonaws.com/0/132627/d772c28c-f01a-b33c-27a2-c2a2c73ae91d.png "スクリーンショット 2016-10-01 15.53.18.png")

## 2. SDKとNDKのパスを通す

### SDKのパスを通す

`Preferences(⌘,) -> Appearance & Behavior -> System Settings -> Android SDK`

![スクリーンショット 2016-10-01 22.03.05.png](https://qiita-image-store.s3.amazonaws.com/0/132627/f873f1c8-b5c5-f152-0ba3-4f9a43e34580.png "スクリーンショット 2016-10-01 22.03.05.png")

### NDKのパスを通す

`Project Structure(⌘;) -> SDK Location`

![スクリーンショット 2016-10-01 22.08.18.png](https://qiita-image-store.s3.amazonaws.com/0/132627/44b5a3e8-43b6-516a-71fb-355d1dd9af53.png "スクリーンショット 2016-10-01 22.08.18.png")

## 3. build.gradleを編集する

現状のbuild.gradleではNDKのビルドをやってくれないため、
APKをビルドしても動かない

そのため、build.gradleないでNDKビルド設定を記述する

また、リソースもコピーされないため、
アセットフォルダにコピーするタスクも追加する

ちなみにNDKのモジュールパスと
アセットにコピーするリソースのパスは
`build-cfg.json`から取得するようにしたため、
変更する場合は、そちらを変更すること

build-cfg.jsonはデフォルトで作られる
(おそらくcocosコマンドで使用される？)

``` build.gradle
apply plugin: 'com.android.application'

import org.apache.tools.ant.taskdefs.condition.Os
import groovy.json.JsonSlurper

android {
    compileSdkVersion 22
    buildToolsVersion "22.0.1"

    defaultConfig {
        applicationId "org.cocos2dx.GameBase"
        minSdkVersion 10
        targetSdkVersion 22
        versionCode 1
        versionName "1.0"
    }

    sourceSets.main {
        jni.srcDirs = []
        java.srcDir "src"
        res.srcDir "res"
        jniLibs.srcDir "libs"
        manifest.srcFile "AndroidManifest.xml"
        assets.srcDir "assets"
    }

    signingConfigs {

       release {
            if (project.hasProperty("RELEASE_STORE_FILE")) {
                storeFile file(RELEASE_STORE_FILE)
                storePassword RELEASE_STORE_PASSWORD
                keyAlias RELEASE_KEY_ALIAS
                keyPassword RELEASE_KEY_PASSWORD
            }
        }
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            if (project.hasProperty("RELEASE_STORE_FILE")) {
                signingConfig signingConfigs.release
            }
        }
    }

    task createAssets << {
        def jsonSlurper = new JsonSlurper()
        def text = new File('build-cfg.json')
        def root = jsonSlurper.parseText(text.getText())

        def resourceId = 0
        def copyResource = { resource ->
            def taskName = "copyResource$resourceId"
            tasks.create(name: taskName, type: Copy) {
                from "$rootDir/" + resource.from.toString()
                into "assets/" + resource.to.toString()
            }
            tasks.findByName(taskName).shouldRunAfter createAssets
            resourceId += 1
        }

        root.copy_resources.each { resource ->
            copyResource(resource)
        }
        root.must_copy_resources.each { resource ->
            copyResource(resource)
        }
    }

    task buildNative(type: Exec, dependsOn: createAssets, description: 'Compile JNI source via NDK') {
        android.applicationVariants.all { variant ->
            commandLine getNdkBuildCmd(),
                    "NDK_OUT=$buildDir/intermediates/ndk/${variant.dirName}/obj",
                    "NDK_LIBS_OUT=$buildDir/intermediates/ndk/${variant.dirName}/lib",
                    "NDK_MODULE_PATH=" + getNdkModulePath()

            copy {
                from "$buildDir/intermediates/ndk/${variant.dirName}/lib"
                into "libs"
            }
        }
    }

    task cleanNative(type: Exec, description: 'Clean JNI object files') {
        android.applicationVariants.all { variant ->
            commandLine getNdkBuildCmd(),
                    "NDK_OUT=$buildDir/intermediates/ndk/${variant.dirName}/obj",
                    "NDK_LIBS_OUT=$buildDir/intermediates/ndk/${variant.dirName}/lib",
                    "NDK_MODULE_PATH=" + getNdkModulePath(),
                    'clean'
        }
    }

    clean.dependsOn 'cleanNative'

    tasks.withType(JavaCompile) {
        compileTask -> compileTask.dependsOn buildNative
    }

    lintOptions {
        abortOnError false
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile project(':libcocos2dx')
}

def getNdkBuildCmd() {
    def ndkDir = android.ndkDirectory.toString()
    if (ndkDir == null) {
        throw new GradleException("NDK location not found. Define location with ndk.dir in local.properties.")
    }
    def ndkBuildCmd = ndkDir + '/ndk-build'
    if (Os.isFamily(Os.FAMILY_WINDOWS)) {
        ndkBuildCmd += '.cmd'
    }

    return ndkBuildCmd
}

def getNdkModulePath() {
    def jsonSlurper = new JsonSlurper()
    def text = new File('build-cfg.json')
    def root = jsonSlurper.parseText(text.getText())
    def ndkModulePath = '.'

    root.ndk_module_path.each { module ->
        ndkModulePath = "$ndkModulePath:$rootDir/" + module
    }

    return ndkModulePath
}
```

gradleを編集すると同期するか聞かれるので、
`Sync Now`を選択

![スクリーンショット 2016-10-02 20.04.04.png](https://qiita-image-store.s3.amazonaws.com/0/132627/1f65b401-bb8c-212c-9677-3dc334cfce11.png "スクリーンショット 2016-10-02 20.04.04.png")


## 4. Gradleをインストール

この工程がいるかどうかわからないけど、
一応ターミナルでgradlewを直接叩いてGradleをインストールする

```
$ ./gradlew
```

![スクリーンショット 2016-10-02 19.37.47.png](https://qiita-image-store.s3.amazonaws.com/0/132627/492c936a-5e97-d20b-6f7b-d99f02ed845f.png "スクリーンショット 2016-10-02 19.37.47.png")

## 5. APKをビルド

メニューの
`Build -> Build APK`
からAPKをビルドする

![スクリーンショット 2016-10-02 19.43.58.png](https://qiita-image-store.s3.amazonaws.com/0/132627/6d92c858-62ea-ad64-f943-c5859ba91fe5.png "スクリーンショット 2016-10-02 19.43.58.png")

## 6. APKをインストール

Build Successしたら、
adbコマンドを使用して実機もしくはシミュレータにインストールする

```
$ adb install -r app/build/outputs/apk/<PROJ_NAME>-Debug.apk
```

![スクリーンショット 2016-10-02 19.51.46.png](https://qiita-image-store.s3.amazonaws.com/0/132627/076c478e-6400-3c5f-0e0d-a2b3147f8edf.png "スクリーンショット 2016-10-02 19.51.46.png")

## 7. 実行

おなじみの画面が出たら成功

![Screenshot_2016-10-02-20-18-01.png](https://qiita-image-store.s3.amazonaws.com/0/132627/b610906d-e561-5b28-d42b-29f7fe5396ce.png "Screenshot_2016-10-02-20-18-01.png")


# 最後に

過去の記事でAndroidStudioをめちゃ叩いたけど、
実際ちゃんと使ってみたら全然Eclipseと桁違いほど使いやすかったので、
今までちゃんと触らなかった自分が恥ずかしい

[cocos2d-xプロジェクトがAndroid Studioビルドできない時の対処](http://qiita.com/tani-shi/items/ef393b9d9911f5185401)

というかcocosはなぜcocosコマンドでビルドする前提になっているんだ？

proj.android-studioってプロジェクトがあるのに
それじゃ意味なくない？

とりあえずやり方をざっと書いたけど、
なんか足りない感じがするので
動かなかったら報告なり、質問いただけると助かります