2011年2月18日金曜日

Android JNI を Eclipse CDT でプロジェクト統合する
<ubuntu 10.10編 その2>

前回の<その1>ではどこのサイトでもAndroid SDKをインストールする解説と同じですが、最後の方は面倒になったので端折ってしまいました。まぁ、あまり細かく書いても初心者さんが見ることはあまりないのでは?って思っていますので。

私(だけなのかもしれません)が今まで作業した方法は、JNIのC部分を別プロジェクトとして作成し、コマンドラインからCコンパイル後、Javaに取り込んで連携させる方法でした。EclipseにCDTをインストールしても、エディタ程度にしか使えないのであまり意味が無いと思っていました。
久しぶりにJNIを本気で取り組むことになり、何か方法が無いかと思い調査を繰り返してたどり着いたので、備忘録的に記載します。因みに参考としましたのが、CDT AndroidというYouTube動画(英語)です。そのままではNDKバージョン、Eclipseバージョン等が異なり環境もCygwinのWindows環境と違います。

では、今回はJNIのJava環境構築とEclipse CDT連携部分です。前回では環境変数として[ANDROID_NDK_ROOT]をexportしていますが、必須なのかの組み合わせテストまでは行っていないので、やや正確性に欠けるかもしれません。

#当初はexportしないで作業していましたが、設定ミス等がありどれがどれに影響したかまでは未調査です。スミマセン。
#まぁ個人的な備忘録のつもりですので。


<前提>
  • 当資料で利用するサンプルは、NDKに同梱されているHello_Jniです。格納されている場所はNDK展開ディレクトリを基本とし、[samples]->[hello-jni]が格納されています。
  • Ubuntu10.10のEclipseは日本語化していません。Ubuntu 10.04では日本語化を行ったのですが、面倒になったのと日本語化するとダメかも?っていう記述を見た記憶があるので、そのままにしています。

<Androidプロジェクト作成>
  • 最初は元となるAndroidプロジェクトを作成しなければ話になりません。メニューバーの[File]->[New]->[Other]を選択すると、下図の画面が表示されます。この中でAndroidProjectを選択します。
  • Androidプロジェクトの設定画面が表示されます。Javaのみならここで設定するだけなんですよねぇ。
  • 今回はNDKサンプルプロジェクトを選択します。下図のように選択して[Finish]ボタンを押します。因みに下図ではTargetNameがAndroid 2.2としていますが、これは単に2.2以降しか開発しないつもりな私の設定です。
  • 取り込みができれば下図のようにProjectExplorerに表示されます。
  • この時点では、単にJavaプロジェクトを生成しただけです。Propertiesを見るとJavaの設定しか存在しません。

<AndroidプロジェクトのC/C++プロジェクト化>
  • 作業対象のJavaプロジェクトを選択して右クリックします。下図のように[New]->[Other]を選択します。
    ※このメニュー中にConvert to a C/C++ Projectを直接選択してもいいです。(笑)
  • 下図の画面中からConvert to a C/C++ Projectを選択し[Next]ボタンを押下。
  • ここの設定画面では、HelloJNIがCで作成されているので、[C Project]を選択しています。次に[Project type]では[Makefile project]を選択し[Toolchain]はそのまま[Other Toolchain]とします。これでC/C++ Project化は終了です。
    というか、この辺りの設定を自分で全て行うことで出来るって意味なんですよねぇ。
  • 念のために、ProjectのPropertiesを見てみます。ちゃんとC/C++のカテゴリが追加されていますよね。

<C/C++プロジェクトのソース設定>
  • Cのビルドに必要なディレクトリを追加します。下図ではプロジェクト選択後、右クリックにて[New]->[Folder]を選択しています。作業し易い方法で構いません。
  • 追加するディレクトリ名は[libs]と[obj]です。下図ではlibsを追加しようとしている状態です。
  • プロジェクトプロパティを変更します。まず最初はコンパイルを行うための[Include]を変更しなければなりません。標準ではUbuntuのgccで必要なファイルが自動設定されています。
    変更場所は、[C/C++ General]->[Paths and Synbols]で最初は[Includes]となります。
  • [Languages]の[Assembly][GNU C][GNU C++]に設定されている内容を全て削除を行います。Shiftキーで複数選択も出来ますが、それほど多く無いので簡単に出来ますね。今回はCのみなのでアセンブラやC++は変更しなくても良いのでしょうが、まぁ勢いです。(笑
  • 全てが空になったら、上記の[Add...]ボタンを押下します。ここで[File system...]ボタンを押下してディレクトリを選択します。
  • NDKのIncludeファイルディレクトリを選択します。下図のように、NDKを展開したディレクトリの[platforms]->[ビルド選択したAndroid OSのAPI Level]->[arch-arm]->[usr]->[include]です。
  • 選択終了すると以下のように、チェックボックスも選択して[OK]ボタンを押下しておきます。
  • 次に[Source Location]の設定を変更します。初期はプロジェクト直下になっているので、本来の位置である[jni]フォルダにしなければなりません。空に出来ないので、[Add Folder...]ボタンでプロジェクト配下の[jni]フォルダを選択し、自動設定された[/HelloJni]を削除します。
  • 最後に[Output Location]です。ここでは、出力結果をどこにするのかを指定しておきます。ここでは、追加した2つのディレクトリである[libs][obj]を追加し、自動設定された[/HelloJni]を削除します。下図は完了した状態です。
  • 変更箇所を適用させるために[Apply]ボタンを押します。するとインクルードパスを変更しているためにリビルドするかを聞いてきますが、ビルド設定が完了出来ていないので[No]にしています。
  • ここまでで、ソースの設定は終了。次はビルド設定になります。
<C/C++プロジェクトのビルド設定>
  • プロジェクトプロパティの[C/C++ Build]を変更します。プロパティを表示し下図のように[C/C++ Build]を表示。その中にある[Builder Settings]の[Use default Build Command]のチェックをオフにし、[Build command]にフルパスでNDKでのビルドコマンドである[ndk-build]を設定します。
    ※フルパス以外ではコンパイルできませんので注意してください。
  • 振る舞いを変更します。下図のように、[Behaiviour]タブの[Buid(incremental build)]欄には、初期値として[all]が記述されていますが、ndk-buildのオプションである[-B]を入れます。[Clean]ですが、ndk-buildはclean動作が不安定との情報もあったのでチェックをオフにしました。
  • 次に左にある[Environment]を選択します。下図の中に<その1>で設定されたパスを通したいので、[Add...]ボタンを押します。
  • 追加用の画面です。[Name]に「PATH」を入力し、値には[Variables]ボタンを押します。
  • 選択画面の中で、PATHを選択し[OK]ボタンを押します。
  • 先ほどの入力画面に戻ります。下図の通り直接入力しても同じですね。(笑)
    [OK]ボタンで追加終了です。
  • 追加完了した[Environment]です。お疲れ様でした。これで無事設定完了となります。
<最終確認>
  • 全ての設定が問題なく行われた場合、Build Projectを行って見ます。下図のように、ナビゲーターで確認していますが、[bin]フォルダには.apkファイルが作成され、[libs][obj]には.soファイルが作成されているのが確認できます。
    コンソールにはC-Buildとしてコンパイルされていることが確認出来ますね。

お疲れ様でした。
これで、JavaやCソースを修正した後に一括ビルド後にエミュレータで確認することが出来るようになります。

5 件のコメント:

  1. こちらのガイドで統合がスムーズに進みました。
    ありがとうございます。

    もしお時間が有れば、C/C++側でのbreakpointの止め方
    など
    統合した上でのDebugに関してもガイドを記載して欲しいです。

    返信削除
  2. 公開が遅れて申し訳ありませんでした。

    C/C++側でのbreakpoint件、GDBServer云々の概要は知っているのですが、面倒で明確な調査は行なっていません。
    今は、Linux側でC/C++のソースをCDEで開発しbreakpoint等でデバッグ完了後に、Android JNI統合するという作業で行なっています。

    NDK中心の開発作業というより、単独ライブラリ開発が主でしたのでUI部分とかAndroidコア部分の開発ではNDKを使用していないためです。
    そろそろ本格的に調査しようかなぁとか思ってはいるので・・・

    返信削除
  3. 非常に詳しく書かれていたので、問題なくEclipseからndk-buildが出来るようになりました。

    分かれば教えていただきたいのですが、設定終了後、Cソースがエラーになってしまいました。内容は”Type 'jstring' could not be resolved" などです。宜しくお願いします。

    返信削除
  4. 投稿コメントがスパムになっておりましたので・・・。 (^^;
    内容が不明なので正確な回答は難しいです。

    #include
    jstring無いエラーなので、上記のincludeが無いのか、またはパスが通っていないのかだろうと想像しますが。
    これ以上は、環境設定すべて、エラーになったCソース、コンパイルエラー、Android.mk等を公開して頂かないと判断できませんよね。

    返信削除
  5. 青柳と申します。

    私もNDKによる開発を行っておりましたが、おかげさまでコード入力が快適になりました!
    CDTってJavaで開発するのと同じ位の快適さがあったのですね。
    (Content Assist, Foldingを動作できたときは「やった!」って感じでした)

    ndk-buildだけはCygwinコンソールの中から実行していますが、今までとは段違いのラクさです。
    記事公開ありがとうございます。

    返信削除