23
21

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Android Studio 2.1.2 で C++ ライブラリ

Last updated at Posted at 2016-07-22

Android Studio 2.1.2 で C++ ライブラリを作ってみた

2016-07: Android Studio の C++ 対応状況

  1. Android Studio で新しいプロジェクトを作ると Gradle Pluginバージョンは 2.1.2 、 Grade のバージョンは 2.10 になってる
    1. Gradle の最新は 2.14.1
    2. Gradle 2.11 以降のリリースノートでは特に Android や C++ に関する言及は無い: 2.14.1, 2.14, 2.13, 2.12, 2.11
  2. Experimental Gradle Plugin に差し替えれば C++ をビルドできる
    1. Google のサンプル では gradle-experimental 0.7.0 を使ってるが0.7.2 がリリースされてる
    2. 2016-08-08: ソースはこれかな?
      1. チケットはこれかな? (でも 2016 年のチケットが見当たらない...)
    3. 2016-08-12: ソースはここからもダウンロードできるっぽい
  3. 従来の Glade Plugin と Experimental Plugin を混在させることができる
  4. まだリリースされてない Android Studio 2.2 では Gradle ではなく ndk-build または CMake を使った C++ 開発を改善する
    1. ndk-build: build.grade の externalNativeBuild で Android.mk を指定できる
    2. cmake: build.grade の externalNativeBuild で CMakeLists.txt を指定できる
    3. コンパイルオプションなども指定できる

方針

  1. メインとなる Java コードに C++ を追加することを想定し

    1. Java アプリは従来の Glade Plugin でビルド
    2. C++ 用のライブラリモジュールを別に作って Experiment Gradle Plugin でビルド
  2. Experimental Gradle Plugin の 0.7.2 を使ってみる

  3. Gradle は 2.10 のまま

環境

  1. Mac OS X 10.11.5 (英語)
  2. Oracle JDK 1.8.0_91
  3. Android Studio 2.1.2
  4. Android NDK r12b

手順

  1. Android Studio で Empty Activity の新しいプロジェクトを作成

  2. ./build.gradle に gradle-experimental を追加

     // Top-level build file where you can add configuration options common to all sub-projects/modules.
    
     buildscript {
     	repositories {
     		jcenter()
     	}
     	dependencies {
     		classpath 'com.android.tools.build:gradle:2.1.2'
     		classpath 'com.android.tools.build:gradle-experimental:0.7.2'
    
     		// NOTE: Do not place your application dependencies here; they belong
     		// in the individual module build.gradle files
     	}
     }
    
     allprojects {
     	repositories {
     		jcenter()
     	}
     }
    
     task clean(type: Delete) {
     	delete rootProject.buildDir
     }
    
  3. 新しい Android Library モジュールを作成

  4. ./app/build.gradle にライブラリモジュールへの依存を追加 (compile project)

     	apply plugin: 'com.android.application'
    
     	android {
     		compileSdkVersion 24
     		buildToolsVersion "24.0.0"
    
     		defaultConfig {
     			applicationId "jp.kenichi.androidapp04"
     			minSdkVersion 15
     			targetSdkVersion 24
     			versionCode 1
     			versionName "1.0"
     		}
     		buildTypes {
     			release {
     				minifyEnabled false
     				proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
     			}
     		}
     	}
    
     	dependencies {
     		compile project(':mylibrary')
     		compile fileTree(dir: 'libs', include: ['*.jar'])
     		testCompile 'junit:junit:4.12'
     		compile 'com.android.support:appcompat-v7:24.0.0'
     	}
    
  5. ./mylibrary/build.gradle を gradle-experimental 用に書き換え

     	apply plugin: 'com.android.model.library'
    
     	model {
     		android {
     			compileSdkVersion 24
     			buildToolsVersion "24.0.0"
    
     			defaultConfig {
     				minSdkVersion.apiLevel 15
     				targetSdkVersion.apiLevel 24
     				versionCode 1
     				versionName "1.0"
     			}
     			//buildTypes {
     			//    release {
     			//        minifyEnabled false
     			//        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
     			//    }
     			//}
     			ndk {
     				moduleName "mylibrary"
     				platformVersion 15
     				cppFlags.addAll(['-std=c++11', '-fexceptions', '-Wall'])
     				ldLibs.addAll(['log'])
     				stl = "gnustl_shared"
     			}
     		}
     	}
    
     	dependencies {
     		compile fileTree(dir: 'libs', include: ['*.jar'])
     		testCompile 'junit:junit:4.12'
     		compile 'com.android.support:appcompat-v7:24.0.0'
     	}
    
    1. com.android.librarycom.android.model.library へ変更
    2. android ブロックを model で囲む
      1. dependenciesmodel の外
    3. minSdkVersiontargetSdkVersion.apiLevel を追加
    4. android ブロックに ndk を追加
    5. ライブラリなので ``buildTypes``` をコメントアウト
    6. addAll ではなく += を使うと紛らわしいエラーが出る: Error:Unable to load class 'com.android.build.gradle.managed.NdkConfig$Impl'.
  6. ライブラリモジュールに Java Class を追加し native メソッドを追加

     public static native String getStringFromJni();
    
  7. 赤字になったメソッド名を選択して、左の赤い「!」から Create function

    1. jni フォルダと C ソースが作成される

    2. JNI メソッドが生成されなかったので、仕方なく自分で記述

       #include <jni.h>
      
       JNIEXPORT jstring JNICALL
       Java_jp_kenichi_mylibrary_LibCppClass_getStringFromJni(JNIEnv *env, jobject instance) {
          return (*env)->NewStringUTF(env, "Hello 世界");
       }
      
  8. MainActivity で定義した native メソッドを使う

    1. ライブラリをロード

       static {
       	System.loadLibrary("mylibrary");
       }
      
    2. layout で TextView に id を付ける

    3. その TextView に JNI から取得した文字列を設定

       ((TextView)findViewById(R.id.messageTextView)).setText(jp.kenichi.mylibrary.LibClass.getStringFromJni());
      
  9. そのまま Run したら couldn't find "libmylibrary.so" エラーが出たが Android Studio を再起動して再度 Run したら動いた

  10. C を C++ に変更

  11. h

       #include <jni.h>
    
       extern "C" {
    
       JNIEXPORT jstring JNICALL
       Java_jp_kenichi_mylibrary_LibClass_getStringFromJni(JNIEnv *env, jobject instance);
    
       }
    
  12. cpp

    	#include "libclass.h"
    
    	JNIEXPORT jstring JNICALL
    	Java_jp_kenichi_mylibrary_LibClass_getStringFromJni(JNIEnv *env, jobject instance) {
    	   return env->NewStringUTF("Hello 世界++");
    	}
    

参考

  1. gradle-experimental 0.7.0 を使う方法
  2. Android Studio で Hello-JNI を作る方法
  3. Android N では STL を 3 個の実装から選べる
    1. LLVM libc++
    2. GNU STL
    3. libstlport
    4. 各実装の説明
23
21
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
23
21

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?