質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

JNI

JNI(Java Native Interface)は、Javaプラットフォームにおいて、Javaで記述されたプログラムと、他の言語で書かれたネイティブコードを連携するためのインタフェース仕様である

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

Q&A

解決済

1回答

2846閲覧

JNIによる文字列呼び出しについて

novice_engineer

総合スコア7

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

JNI

JNI(Java Native Interface)は、Javaプラットフォームにおいて、Javaで記述されたプログラムと、他の言語で書かれたネイティブコードを連携するためのインタフェース仕様である

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

0グッド

0クリップ

投稿2017/10/23 06:46

編集2017/10/24 05:21

AndroidStudioにてJNIを用いてC言語の文字列をJavaへ受け渡したいと考えています.
NDK-Buildを使い共有ライブラリの作成も行いましたがJavaコード内で
定義したC言語の関数名が反応せずエラーが発生しています.

この場合作成した共有ライブラリに問題があるのか,または開発環境の設定に問題があるのでしょうか?

プロジェクト構成図及びエラー画面

C

1#include "hello-jni.h" 2 3JNIEXPORT jstring JNICALL 4Java_android_mobi_monaca_HelloWorldPlugin_stringFromJNI( JNIEnv* env, 5 jobject thiz ) 6{ 7 return (*env)->NewStringUTF(env, "Hello from JNI test !"); 8}

gradle

1 2apply plugin: 'com.android.application' 3 4buildscript { 5 repositories { 6 mavenCentral() 7 jcenter() 8 } 9 10 dependencies { 11 classpath 'com.android.tools.build:gradle:2.3.2' 12 } 13} 14 15allprojects { 16 repositories { 17 mavenCentral(); 18 jcenter() 19 } 20} 21 22task wrapper(type: Wrapper) { 23 gradleVersion = '2.14.1' 24} 25 26ext { 27 apply from: 'CordovaLib/cordova.gradle' 28 if (!project.hasProperty('cdvCompileSdkVersion')) { 29 cdvCompileSdkVersion = null; 30 } 31 if (!project.hasProperty('cdvBuildToolsVersion')) { 32 cdvBuildToolsVersion = null; 33 } 34 if (!project.hasProperty('cdvVersionCode')) { 35 cdvVersionCode = null 36 } 37 if (!project.hasProperty('cdvMinSdkVersion')) { 38 cdvMinSdkVersion = null 39 } 40 if (!project.hasProperty('cdvBuildMultipleApks')) { 41 cdvBuildMultipleApks = null 42 } 43 if (!project.hasProperty('cdvReleaseSigningPropertiesFile')) { 44 cdvReleaseSigningPropertiesFile = null 45 } 46 if (!project.hasProperty('cdvDebugSigningPropertiesFile')) { 47 cdvDebugSigningPropertiesFile = null 48 } 49 if (!project.hasProperty('cdvBuildArch')) { 50 cdvBuildArch = null 51 } 52 53 cdvPluginPostBuildExtras = [] 54} 55 56// PLUGIN GRADLE EXTENSIONS START 57// PLUGIN GRADLE EXTENSIONS END 58 59def hasBuildExtras = file('build-extras.gradle').exists() 60if (hasBuildExtras) { 61 apply from: 'build-extras.gradle' 62} 63 64// Set property defaults after extension .gradle files. 65if (ext.cdvCompileSdkVersion == null) { 66 ext.cdvCompileSdkVersion = privateHelpers.getProjectTarget() 67} 68if (ext.cdvBuildToolsVersion == null) { 69 ext.cdvBuildToolsVersion = privateHelpers.findLatestInstalledBuildTools() 70} 71if (ext.cdvDebugSigningPropertiesFile == null && file('debug-signing.properties').exists()) { 72 ext.cdvDebugSigningPropertiesFile = 'debug-signing.properties' 73} 74if (ext.cdvReleaseSigningPropertiesFile == null && file('release-signing.properties').exists()) { 75 ext.cdvReleaseSigningPropertiesFile = 'release-signing.properties' 76} 77 78// Cast to appropriate types. 79ext.cdvBuildMultipleApks = cdvBuildMultipleApks == null ? false : cdvBuildMultipleApks.toBoolean(); 80ext.cdvMinSdkVersion = cdvMinSdkVersion == null ? null : Integer.parseInt('' + cdvMinSdkVersion) 81ext.cdvVersionCode = cdvVersionCode == null ? null : Integer.parseInt('' + cdvVersionCode) 82 83def computeBuildTargetName(debugBuild) { 84 def ret = 'assemble' 85 if (cdvBuildMultipleApks && cdvBuildArch) { 86 def arch = cdvBuildArch == 'arm' ? 'armv7' : cdvBuildArch 87 ret += '' + arch.toUpperCase().charAt(0) + arch.substring(1); 88 } 89 return ret + (debugBuild ? 'Debug' : 'Release') 90} 91 92// Make cdvBuild a task that depends on the debug/arch-sepecific task. 93task cdvBuildDebug 94cdvBuildDebug.dependsOn { 95 return computeBuildTargetName(true) 96} 97 98task cdvBuildRelease 99cdvBuildRelease.dependsOn { 100 return computeBuildTargetName(false) 101} 102 103task cdvPrintProps << { 104 println('cdvCompileSdkVersion=' + cdvCompileSdkVersion) 105 println('cdvBuildToolsVersion=' + cdvBuildToolsVersion) 106 println('cdvVersionCode=' + cdvVersionCode) 107 println('cdvMinSdkVersion=' + cdvMinSdkVersion) 108 println('cdvBuildMultipleApks=' + cdvBuildMultipleApks) 109 println('cdvReleaseSigningPropertiesFile=' + cdvReleaseSigningPropertiesFile) 110 println('cdvDebugSigningPropertiesFile=' + cdvDebugSigningPropertiesFile) 111 println('cdvBuildArch=' + cdvBuildArch) 112 println('computedVersionCode=' + android.defaultConfig.versionCode) 113 android.productFlavors.each { flavor -> 114 println('computed' + flavor.name.capitalize() + 'VersionCode=' + flavor.versionCode) 115 } 116} 117 118android { 119 sourceSets { 120 main { 121 manifest.srcFile 'AndroidManifest.xml' 122 java.srcDirs = ['src'] 123 resources.srcDirs = ['src'] 124 aidl.srcDirs = ['src'] 125 renderscript.srcDirs = ['src'] 126 res.srcDirs = ['res'] 127 assets.srcDirs = ['assets'] 128 jniLibs.srcDirs = ['libs'] 129 } 130 } 131 132 defaultConfig { 133 versionCode cdvVersionCode ?: new BigInteger("" + privateHelpers.extractIntFromManifest("versionCode")) 134 applicationId privateHelpers.extractStringFromManifest("package") 135 136 if (cdvMinSdkVersion != null) { 137 minSdkVersion cdvMinSdkVersion 138 } 139 } 140 141 lintOptions { 142 abortOnError false; 143 } 144 145 compileSdkVersion cdvCompileSdkVersion 146 buildToolsVersion cdvBuildToolsVersion 147 148 if (Boolean.valueOf(cdvBuildMultipleApks)) { 149 productFlavors { 150 armv7 { 151 versionCode defaultConfig.versionCode*10 + 2 152 ndk { 153 abiFilters 'armeabi-v7a' 154 } 155 } 156 x86 { 157 versionCode defaultConfig.versionCode*10 + 4 158 ndk { 159 abiFilters 'x86' 160 } 161 } 162 all { 163 ndk { 164 abiFilters "all", "" 165 } 166 } 167 } 168 } 169 170 171 compileOptions { 172 sourceCompatibility JavaVersion.VERSION_1_6 173 targetCompatibility JavaVersion.VERSION_1_6 174 } 175 176 if (cdvReleaseSigningPropertiesFile) { 177 signingConfigs { 178 release { 179 // These must be set or Gradle will complain (even if they are overridden). 180 keyAlias = "" 181 keyPassword = "__unset" // And these must be set to non-empty in order to have the signing step added to the task graph. 182 storeFile = null 183 storePassword = "__unset" 184 } 185 } 186 buildTypes { 187 release { 188 signingConfig signingConfigs.release 189 } 190 } 191 addSigningProps(cdvReleaseSigningPropertiesFile, signingConfigs.release) 192 } 193 if (cdvDebugSigningPropertiesFile) { 194 addSigningProps(cdvDebugSigningPropertiesFile, signingConfigs.debug) 195 } 196} 197 198dependencies { 199 compile fileTree(dir: 'libs', include: '*.jar') 200 // SUB-PROJECT DEPENDENCIES START 201 debugCompile(project(path: "CordovaLib", configuration: "debug")) 202 releaseCompile(project(path: "CordovaLib", configuration: "release")) 203 // SUB-PROJECT DEPENDENCIES END 204} 205 206def promptForReleaseKeyPassword() { 207 if (!cdvReleaseSigningPropertiesFile) { 208 return; 209 } 210 if ('__unset'.equals(android.signingConfigs.release.storePassword)) { 211 android.signingConfigs.release.storePassword = privateHelpers.promptForPassword('Enter key store password: ') 212 } 213 if ('__unset'.equals(android.signingConfigs.release.keyPassword)) { 214 android.signingConfigs.release.keyPassword = privateHelpers.promptForPassword('Enter key password: '); 215 } 216} 217 218gradle.taskGraph.whenReady { taskGraph -> 219 taskGraph.getAllTasks().each() { task -> 220 if (task.name == 'validateReleaseSigning' || task.name == 'validateSigningRelease') { 221 promptForReleaseKeyPassword() 222 } 223 } 224} 225 226def addSigningProps(propsFilePath, signingConfig) { 227 def propsFile = file(propsFilePath) 228 def props = new Properties() 229 propsFile.withReader { reader -> 230 props.load(reader) 231 } 232 233 def storeFile = new File(props.get('key.store') ?: privateHelpers.ensureValueExists(propsFilePath, props, 'storeFile')) 234 if (!storeFile.isAbsolute()) { 235 storeFile = RelativePath.parse(true, storeFile.toString()).getFile(propsFile.getParentFile()) 236 } 237 if (!storeFile.exists()) { 238 throw new FileNotFoundException('Keystore file does not exist: ' + storeFile.getAbsolutePath()) 239 } 240 signingConfig.keyAlias = props.get('key.alias') ?: privateHelpers.ensureValueExists(propsFilePath, props, 'keyAlias') 241 signingConfig.keyPassword = props.get('keyPassword', props.get('key.alias.password', signingConfig.keyPassword)) 242 signingConfig.storeFile = storeFile 243 signingConfig.storePassword = props.get('storePassword', props.get('key.store.password', signingConfig.storePassword)) 244 def storeType = props.get('storeType', props.get('key.store.type', '')) 245 if (!storeType) { 246 def filename = storeFile.getName().toLowerCase(); 247 if (filename.endsWith('.p12') || filename.endsWith('.pfx')) { 248 storeType = 'pkcs12' 249 } else { 250 storeType = signingConfig.storeType // "jks" 251 } 252 } 253 signingConfig.storeType = storeType 254} 255 256for (def func : cdvPluginPostBuildExtras) { 257 func() 258} 259 260// This can be defined within build-extras.gradle as: 261// ext.postBuildExtras = { ... code here ... } 262if (hasProperty('postBuildExtras')) { 263 postBuildExtras() 264} 265

フォルダ構成図

  • Cのビルド方法
  1. 上記のCのソースコードを作成,編集
  2. NDK-Buildコマンドでビルド
  3. 上記のandroid/src/libsフォルダ内にアーキテクチャごとに.soファイルが生成

といった順序で共有ライブラリの作成を行いました.

AndroidStudio内のjniLibsフォルダに共有ライブラリを移動したい場合は
android/src/libsに生成されたsoファイルをandroid/libsにコピーすることで
AndroidStudio内でのjniLibsフォルダにコピーが反映されます.

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

私の環境でも、JNI使おうとするとそうなります。

AndroidStudioがシンボルを見つけられておらず、
エディタのフォントカラー設定で赤くなっているだけなので
書き方が間違っていなければそのままビルドが通ると思います。

投稿2017/10/23 08:54

abs123

総合スコア1280

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

novice_engineer

2017/10/23 13:04

abs123さん 回答ありがとうございます. ご指摘いただいた通りビルドではエラーが検知されませんね. しかしシミュレータで動作を確認しようとすると System.loadLibrary("hello-jni"); の行でプログラムが動作を停止してしまうため, 私の場合ではエラーとして検知されているようでした.
abs123

2017/10/24 00:46

フォルダ構成を見た限りでは、soファイルの取り込みが上手くいってなさそうな気がします。 下記の情報がほしいです。 ・logcatのエラーメッセージ ・CソースをBuildしたときの手順 ・アプリフォルダ配下のbuld.gradle ・ファイルエクスプローラ上でのフォルダ構成 この問題に追記するか、別途質問を投稿するかはお任せします。
novice_engineer

2017/10/24 05:25

abs123さん ご返信ありがとうございます. 質問文にフォルダ構成図やCのビルド手順,gradleファイルについて追記しました. プロジェクトについてですが,CordovaプロジェクトをAndroidStudioにて編集しているため 通常の構成とは少し異なるかと思います.
abs123

2017/10/24 06:30

Cordovaあまりよく知らないのであれですが、 build.gradleの内容を確認した限り、android/libs内にsoファイルを配置する必要があると思います。 android/src/libs 配下の内容をそのまま android/libs にコピーする感じです。 取り込みに成功しているかの確認方法としては、生成されたAPKをZIPとして展開し、 中に lib/アーキテクチャ名ディレクトリ/soファイル の形で配置されていれば取り込めていると思います。
novice_engineer

2017/10/25 09:13

abs123さん ご返信ありがとうございます! おかげで問題を解決することが出来ました! Cordovaプロジェクトでは1枚目の画像ではJavaのコードが package android.mobi.monaca; にコードが格納されていますが実際にはこちらを package mobi.monaca; に修正しないとJavaのコードそのものが反応していなかった様です. そのため,Cのコードでも関数名を Java_mobi_monaca_HelloWorldPlugin_stringFromJNI に修正し,NDK-buildを行い,作成された共有ライブラリを ご指摘いただいたフォルダにコピーすることでCからJavaへ受け渡した 文字列がアラートで表示されました! 最終的にJavaコード内のCのメソッド宣言は赤字のまま, またpackageの部分も赤い波線が表示されてしまいますが, 無事にビルドされ動作も問題ないようでした! 長くなってしまいましたがお付き合い頂きありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問