ラベル Android-NDK の投稿を表示しています。 すべての投稿を表示
ラベル Android-NDK の投稿を表示しています。 すべての投稿を表示

2019年6月1日土曜日

Unity で 64bit版 Anrdoid アプリをビルドする方法

How to build 64-bit Android Applications with Unity3D

2019 年 8 月 1 日から Googole Play で公開するネイティブコードを使用するアプリは、64bit版のコードを含んでいることが必須になります。
それ以降は 32bit のネイティブコードのみを使用するアプリの公開ができなくなることが決まっています。
Android Studio で Java や Kotlin でプログラミングしたアプリならネイティブコードの心配はありませんが、ゲームエンジンの Unity3D (以下 Unity) でビルドした Android アプリはネイティブコードを含むので注意が必要です。
Unity で 64bit のネイティブコードを含めた Andorid アプリをビルドする方法を試してみたのでその方法をまとめました。
blog.fujiu.jp Unity で 64bit版 Anrdoid アプリをビルドする方法


環境

  • Windows 10
  • Unity Editor 2019.1.4


Unity のツール類のパスを確認する

Unity を起動しメニューの
Edit -> Preferences
を開き、JDK・Android SDK・Android NDK のパスが設定されているか確認します。
設定されていなければそれぞれインストールする必要があります。


Java SE Developpment Kit 8 (JDK8) をインストールする

JDK 8 がインストールされていない場合は公式サイトからダウンロードしインストールします。
https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html

インストールしたら Unity の Preferences にインストールしたパスを設定します。


Android SDK (Android Studio) をインストールする

Android SDK がインストールされていない場合は Android Studi のインストールをおすすめします。
Android SDK はコマンドラインツールとして公開されていますが、Android Studio をインストールすると Android SDK を GUI でアップデートできます。
Android Studio は公式サイトからダウンロードできます。
https://developer.android.com/studio

Android Studio を起動し、メニューの
Files -> Settings
で Settings 画面を開き
Appearance & Behavior -> System Settings -> Android SDK
の階層にある Android SDK Location の項目が Android SDK のパスです。

このブログを書いている時点では Unity には Android SDK Tool 26.1.1 が必要でした。
Android SDK Tool のバージョンは SDK Tools タブで確認出来ます。
バージョンが古い場合はこの画面からアップデート出来ます。

Android SDK をインストールしたら Unity の Preferences にインストールしたパスを設定します。


Android NDK をダウンロードし展開する

Android NDK がインストールされていない場合はインストールする必要があります。
このブログを書いている時点 Android NDK の最新バージョン r19c は Unity では使えず、少し古めのバージョン r16b が必要です。
古いバージョンの Android NDK は NDK アーカイブからダウンロードできました。
https://developer.android.com/ndk/downloads/older_releases.html?hl=ja
Android NDK のインストールはダウンロードした zip ファイルを展開するだけです。
展開したら Unity の Preferences に展開したパスを設定します。


Platform を切り替えて Android-Support-for-Editor をインストールする

Unity のメニューの
File -> Build Settings
を開き
Platform の Android を選択して Switch Platform をクリックします。

Android-Support-for-Editor がインストールされていない場合は、ここでダウンロードを促されます。
Android-Support-for-Editor をダウンロードしたらインストールし、もう一度上記画面の Switch Platform をクリックします。


Player Settings を設定するする

Build Settings の左下の Player Settings をクリックします。
Other Settings の階層の設定項目を次のように変更します。
  • Scripting RUntime Version を .NET 4.x Equivalent にする
  • Scriopting Backend を IL2CPP にする
  • ARM64 のチェックをオンにする

この設定で Build Settings の Build をクリックすれば 64bitのネイティブコードを使用する Android アプリにビルドすることが出来ました。
Android 端末実機の USB デバッグをオンにして USB ケーブルで接続して Build And Run をクリックすれば実機で動作テスト出来ます。

Androd Studio で 64bit のネイティブコードを含んでいるか確かめる方法は Android アプリの 64bit 必須化に対応する方法 で公開しています。


エラーが出たときの対処方法

Feature `out variable declaration' cannot be used error というエラーが出た場合

Other Settings の Scripting RUntime Version を .NET 4.x Equivalent に設定する


関連ブログ

Android アプリの 64bit 必須化に対応する方法
[Unity3D] Unity5のプロジェクトをAndroid Studioにインポートする方法


2019年2月9日土曜日

Android アプリの 64bit 必須化に対応する方法

How to support 64 bit libraries

2019年1月、Google Play で公開する一部のアプリは 64bit 対応が必須であることが発表されました。
Android Studio などで開発した 64bit に対応していないネイティブコードを含むアプリは2019年8月以降 Google Play から段階的に削除される可能性があります。
翻訳が間違っていたらすみません。
https://android-developers.googleblog.com/2019/01/get-your-apps-ready-for-64-bit.html

Android Studio で開発したアプリの 64bit 対応状況の調べ方と 64bit 化する方法をまとめました。


環境

  • Windows 10
  • Android Studio 3.3


64bit への対応が必要な条件

自作やサードパーティ製にかかわらず、C/C++ などで開発したネイティブコードを含むアプリは 64bit 版 x86 と 64bit 版 ARM のネイティブコードをサポートする必要があります。
32bit のライブラリを使わず、Java や Kotlin のみで開発したアプリなら必要ないと解釈出来ます。

原文はこちら
Uses any C/C++ (native) code in your app.
Links with any third party native libraries.
Is built by a third-party app builder that uses native libraries.

For the ARM architecture, the 32-bit libraries are located in armeabi-v7a. The 64-bit equivalent is arm64-v8a.
For the x86 architecture, look for x86 for 32-bit and x86_64 for 64-bit.


ネイティブコードを含んでいるかを確認する方法

Android Studio で自作したアプリの APK ファイルを調べてネイティブコードを含んでいるかを確認する方法です。
メニューから
Build -> Analyze APK
を開きます。

File ツリーが表示され、ネイティブコードを含むアプリは lib フォルダーがあります。
lib を展開し arm64-v8a と x86_64 のフォルダーに so ファイルがあればそれが 64bit のネイティブコードです。


自作ネイティブコードを 64bit 化する方法

apk ファイルの lib フォルダーに 64bit の so ファイルがなければ 64bit の so ファイルをビルド(コンパイル)する必要があります。
so ファイルのビルド方法はコンパイラーごとに異なるので公式サイトに載っていた方法をまとめました。


Gradle でネイティブコードをビルドする場合

build.gradle の
android -> defaultConfig
の ndk.abiFilters の行を次のように記述します。


CMake でネイティブコードをビルドする場合

arm64-v8a の so ファイルをビルドするには次のコマンドラインオプションを使います。


x86_64 の so ファイルをビルドするには次のコマンドラインオプションを使います。


ndk-build でネイティブコードをビルドする場合

app.mk ファイル (Android.mk) の APP_ABI の行を次のように記述します。


これら以外の方法でコンパイルしている場合はそれに合わせた 64bit のコンパイルが必要です。


参考にしたサイト

Ensure that your app supports 64-bit devices | Android Developers https://developer.android.com/distribute/best-practices/develop/64-bit


関連ブログ

Eclipse の Android Project を Android Studio にインポートしてビルドする方法
[Android] Xamarin で jar (Javaライブラリー) を実行する方法
[Android Studio] Xamarin で実行可能な jar (Javaライブラリー) の作り方
[Unity3D] Unity5のプロジェクトをAndroid Studioにインポートする方法


2018年10月13日土曜日

Eclipse の Android Project を Android Studio にインポートしてビルドする方法

How to import Eclipse projects to Android Studio

Google Play の2018年11月のアップデートで Target SDK が 26 以上(Android 4.0 以上) のアプリでなければ公開できない制限が設けられました。
当ブログの著者が公開していたアプリは Android 1.6 以上のものが多く、制限を受けることになるためアップデートに対応することにしました。
当時は Eclipse で開発しましたが、現在は Eclipse Android デベロッパーツールのサポートが終了しているため Android Studio にインポートしてビルドしました。
Eclipse で開発したプロジェクトを Android Studio にインポートしてから APK ファイルを作成するまでに必要だった手順をまとめました。


環境

  • Windows 10
  • Android Studio 3.1.4


Eclipse のプロジェクトをインポートする

Android Studio を起動します。下のような画面ではなければメニューの
File - Close project
をクリックすると下のような画面になります。
blog.fujiu.jp Eclipse の Android Project を Android Studio にインポートしてビルドする方法

右側の下の方にある Import Project をクリックし、Eclipse のワークスペースからインポートしたいプロジェクトのパスを指定します。
インポートできるプロジェクトは一度の操作に一つですが、 別の Eclipse プロジェクト(Facebook Android SDK など)を参照している場合は一緒にインポートしてくれました。


インポートしたプロジェクトを修正する

この後いろいろなエラーが発生するのですが、そのうちの半分くらいはクリックするだけで解決しました。

たとえば下のようなエラーは「Add Google Maven repository and sync project」クリックするとインストールが必要なビルドツールのインストールができます。

下のようなエラーでは「Install build tools ・・・」をクリックします。

Install missing platform(s) and sync project
というエラーもクリックで解決しました。

gradle.build や AndroidManifests.xml のエラーは下のように電球のアイコンをクリックすると解決策が表示されることがあります。

クリックだけで解決したエラーは以下省略します。


build.gradle を手直しする

gradle.build の
Configuration 'compile' is obsolete and has been replaced with 'implementation' and 'api'.
というエラーはクリックで解決しないので compile を implementation に書き換えます。

必須ではありませんが、android {} の中に次のオプションを追加しました。



AndroidManifests.xml を手直しする

Eclipse では SDK のバージョンを AndroidManifests.xml で指定していました。
Android Stuio では SDK のバージョンを build.gradle で指定するのですが、今回は次のように設定を変更しました。

manifest 要素に次の属性を追加する


uses-sdk 要素を次のように書き換える




C/C++ コード (JNI) を含む場合は SDK Tools の追加インストールと Android.mk の設定をする

インポートしたプロジェクトには C/C++ のソースコードを含んでいるものもありました。
Eclipse で開発していたときは手動で ndk-build コマンドを毎回実行していましたが Android Studio ではビルドするための設定が必要でした。
メニューの
Tools - SDK Manager
を開いて
Appearance & Behavior > System Settings > Android SDK
の SDK Tools の次の3つの項目にチェックを入れます。

LLDB
CMake
NDK

上のチェックを入れ終わったら Project ビューの C/C++ のソースを含むプロジェクトを右クリックして
Link C++ Project with Gradle
をクリックします。

Build System を ndk-build にして Android.mk ファイルのパスを指定します。


Project Structures を手直しする

このまま署名済み APK ファイルを作成すると

Gradle DSL method not found: 'storeFile()'

というエラーが起きるため、Project Structures を次の通りに設定する必要がありました。
左の一覧からアプリケーションを選択します。モジュールライブラリーなどがある場合はすべて下の設定が必要です。 て Signing タブで設定を追加します。
下の画像では config という名前で追加しています。
keystore ファイルの指定とエイリアス名・パスワード

Flavors タブで Sigining Config を上で追加した config に設定します。

Build Types タブの Relese の Signing Config を追加した config に設定します。


その他のエラーと解決した対処方法

Cannot fit requested classes in a single dex file. Try supplying a main-dex list.

build.gradle の dependencies {} の中に

を追加して

build.gradle の defaultConfig {} の中に
を追加したら解決しました。

Program type already present ・・・.BuildConfig

Unity 3D でビルドしをプロジェクトを継承したプロジェクトで起きました。
今回は別の方法で対処しましたが、StackOverFlowなどによるとライブラリーモジュールのパッケージ名とアプリケーションとは別のパッケージ名に設定すると回避出来るとのことです。

メニューの
Build -> Generate Signed Bundle / APK
を実行して APK ファイルが生成出来れば完成です。


関連ブログ

Android Studioを使ってみました
[Unity3D] Unity のプロジェクトをAndroid Studio にインポートする方法
[Android Studio] Xamarin で実行可能な jar (Javaライブラリー) の作り方


2014年1月4日土曜日

[Android] アナログ時計のアプリをC/C++で改良

Analog clock on OpenGL by Android-NDK
前回の アナログ時計アプリ のOpenGLの部分をC/C++言語で書けるだけ書いてみました。

C/C++を利用した場合、Javaだけで書いたアプリと比べると次のような特徴があります。
・マシン語で動作するコードの比率が増える
・C/C++出使用するオブジェクトはガーベジコレクター(GC)の対象にならない
このおかげでアプリの高速化やバッテリー消費を抑えるなどの効果が期待できます。

今回の開発環境は次の通りです。
・64bit版 Windows8
・32bit版 Eclipse3.7 (Windows XPモードで使用)
・Android-SDK r22.3
・Android-NDK r9

針の画像です。
左から秒針、分針、時針のつもりです。
針の画像それぞれのピクセル数は32×128です。一番右の黒い塗りつぶしの領域は使用しません。

Eclipseのパッケージ・エクスプローラーで、プロジェクトの res フォルダーの下に
drawable-nodpi
というフォルダーを作り針の画像を配置します。

以下ソースです。
※ Android.mk と jni.cpp と glu.h の3つのファイルはEclipseのプロジェクト・エクスプローラーでjniというフォルダーを作ってそこに保存します。

アクティビティ(MainActivity.java)

Android.mk

jni.cpp

glu.h (Android-NDKのsampleの com.example.SanAngeles から抜粋しました)
※特別な権限(Permission)は不要なのでマニフェストは省略します。
Target SDK Version が4以上の設定でビルドできます。
Android1.6以降で動作します。
Android-NDKのビルド方法は環境に強く依存するので省略させて頂きます。
SH-03C(実機)、Android-SDK付属のエミュレーター、Blue Stacksで動作することを確認していますが動作保証は出来ません。

エミュレーターのスクリーンショットです。
前回のJavaだけで書いたアプリと同じように動作するように作ったので見た目の変化はありません。
1秒に1回しか画面が変化しないので、ログまでチェックしないとGCが減ったかどうかは分かりにくいですね。

関連ブログ
[Android] アナログ時計のアプリを作ってみました
[Android] ストップウォッチアプリの表示をC言語でスムーズに改造する
[Android] ストップウォッチアプリを作ってみました
[Android] 方位センサーを使ってコンパスアプリを作る
[Android] OpenGLでプロ生ちゃんをアニメーションさせる
[Windows8][Android] Can't bind to local 8600 for debugger
[Android] 端末の傾きに立方体を連動させる
[Android] フリーサイズの画像をOpenGLのテクスチャに表示する
[Android] Android-NDKでテクスチャを表示するには
[Android] OpenGLで頂点の多いポリゴンを扱うには

以上、参考になれば幸いです。

2013年11月16日土曜日

[Android] ストップウォッチアプリの表示をC言語でスムーズに改造する

The simple stopwatch application for Android
前回のストップウォッチアプリ は、経過時間の表示がカクカクになることがあります。

経過時間の文字列を表示するため Handler#handleMessage メソッドの中で
ByteArrayOutputStram
と
PrintStream
のインスタンスが1秒間に数十回メモリーのヒープと呼ばれる領域に確保されます。表示後はインスタンスが不要になります。
Javaの仕様により不要になったインスタンスがある程度たまるとヒープから解放する処理が行われます。
(解放されたメモリーは別のインスタンスの確保などに再利用されます)
この処理はGC(ガーベジコレクター、ガーベジコレクション)というものですが、GCの処理は意外と時間がかかるようです。
Android OSのバージョンにもよりますが、GCが完了するまでそれ以外の処理は一時停止されます。

前回のアプリは数秒ごとにGCが発生するため表示がカクカクする原因になっていました。
そこで表示をスムーズにする方法を考えてみました。

C言語ではメモリーの解放処理をプログラムする必要がありますが、GCの対象にはならないので表示をスムーズにできると予想できます。
その結果、経過時間の文字列はJavaではなくAndroid-NDKによるC言語で処理することにしました。

このブログを書いている時点の開発環境は次の通りです。
・Windows8 (64bit)
・Eclipse Juno (32bit)(XP互換モードで起動)
・Android SDK r22.2
・Android NDK r9

以下ソースです。
MainActivity.java (アクティビティ)

※初期化漏れがあったので修正しました。2014年6月16日

jni.cpp


Android.mk


※特別な権限(Permission)は不要なのでマニフェストは省略します。
Target SDK Version が4以上の設定でビルドできます。
Android1.6以降で動作します。
Android-NDKのビルド方法は環境に強く依存するので省略させて頂きます。
SH-03C(実機)とBluestacks(エミュレーター)で動作することを確認しています。

動作保証はできませんが最低限の動作はするようです。
前回に比べてレイアウトを少し変更してます。
アプリ動作中のスクリーン消灯もオフにしています。

GCの頻度を減らしただけですがJavaだけで作ったアプリに比べてかなりスムーズになりました。
今回のC言語のプログラムはスタック変数しか使ってないので解放処理が不要でした。

Javaはメモリーの解放処理が(完全ではないものの)GCにより自動化されているため、プログラムしやすい言語です。
その反面、GCを完全になくすことはできません。
AndroidアプリでGCを減らしたい場合、GCが多発する処理をAndroid-NDKによるC言語でプログラムするのもいい方法だと思います。

関連ブログ
[Android] ストップウォッチアプリを作ってみました
[Android] Javaのstaticクラス(Handler)から非sataticクラス(Activity)のメソッドを呼び出すには(弱参照)
[Android] PrintStream#printfの最適化(SDK r08でのエラーを別の方法で解決する)
[Android] ライブ壁紙の作り方
[Android] 方位センサーを使ってコンパスアプリを作る
[Android] OpenGLでプロ生ちゃんをアニメーションさせる
[Windows8][Android] Can't bind to local 8600 for debugger

以上、参考になれば幸いです。

2013年7月6日土曜日

[Android] Android-NDK(JNI)で画像ファイルをデコードする

How to decode image files on JNI
前回 までにOpenGLとAndroid-NDK(JNI)で画像をテクスチャとして表示するアプリのソースをいくつか紹介させて頂きました。
前回はAndroid-SDK(Java)のAPIを使って画像ファイルをRBGのビットマップ配列にデコードし、JNIに渡す方法を使いました。

今回はAndroid-NDKを使ってJNIでSDカード内の画像ファイルをデコードする機能を作ってみました。

仕様は次の通りです。
1. JavaのコードからJNIに画像ファイルのパスを渡す。
2. JNIで画像ファイルをデコードしint配列のビットマップとしてJavaで受け取る。
3. int配列のビットマップをImageViewerに表示する。

JNI(C言語)で画像ファイルをデコードするため
http://nothings.org/
で公開されている stb_image.c を使いました。

stb_image.c はプロジェクトの
jni
フォルダーにコピーします。C言語のソースファイルやAndroid.mkと同じ場所です。


このブログを書いている時点の開発環境は次の通りです。
・Windows8 (64bit)
・Eclipse Juno (32bit)(XP互換モードで起動)
・Android SDK r21.0.1
・Cygwin
・Android-NDK-r8d

以下ソースです。

MainActivity.java

activity_main.xml (res/layoutフォルダー)

jni.cpp

Android.mk

※特別な権限(Permission)は不要なのでマニフェストは省略します。
Target SDK Version が4以上の設定でビルドできます。
Android1.6以降で動作します。
Android-NDKのビルド方法は環境に強く依存するので省略させて頂きます。

実行するとSDカードを検索して最初に見つけた画像を表示します。
ボタンをタップするたびに画像ファイルを見つけた順に表示します。
前回同様Anndroid2.xでは OutOfMemoryError が起きやすいです。改善の余地ありです。

JNIとJavaとで画像ファイルをint配列にデコードするまでの時間を比べてみました。
測定したのはONDA Vi30というAndroid4.1.1の中華Padです。
過去のベンチマークからVi30はthumbモードよりarmモードの方が速いことが分かっているのでarmモードでビルドしました。

画像のサイズ
JNI
Java
600 x 1024
82ms
189ms
950 x 483
62ms
82ms
1680 x 1050
199ms
257ms

全く同じ処理内容ではないので断言できませんがJNIの方が速そうです。

余談
JNIで画像の伸縮ができればJavaを使わずにOpen GLのテクスチャー用に加工することができるはずです。
前回 悩まされた OutOfMemoryError も減るはず、と思ったのですが残念ながらAndroid-NDKにはCanvas APIがありません。
とても難しそうですがいつかはチャレンジしてみたいと思います。

関連ブログ
[Android] OpenGLの簡易画像ビュアーをAndroid-NDKでビルドする (失敗談)
[Android] BitmapクラスのOutOfMemoryErrorを防ぐ
[Android] BitmapクラスのOutOfMemoryErrorを防ぐ #2
[Android] フリーサイズの画像をOpenGLのテクスチャに表示する
[Android] OpenGLで簡易画像ビュアーを作る
[Android] ジェスチャーでOpenGL簡易画像ビュアーに拡大縮小機能を追加する
[Android] OpenGLでプロ生ちゃんをアニメーションさせる
[Android] OpenGL ESで文字を表示する
[Android] OpenGLで頂点の多いポリゴンを扱うには
[Android] OpenGLでシャープ製端末用3D(立体視)アプリケーションを作る
[Blender] obj2opengl.plをJava用に改造する
[Windows8][Android] Can't bind to local 8600 for debugger

以上、参考になれば幸いです。

2013年6月29日土曜日

[Android] OpenGLの簡易画像ビュアーをAndroid-NDKでビルドする (失敗談)

OpenGL and JNI
AndroidアプリをAndroid-NDKで開発するとネイティブコード(Javaインタープリターを通らないマシン語)で書かれたJNI(Java Native Interface)の動作比率を増やすことができ、Javaだけで開発したアプリに比べて高速な動作やバッテリーの長持ちが期待できます。
Android-NDKで開発するデメリットとして「マルチプラットフォーム(CPUが異なる端末)で動作しなくなる」という点があげられます。
Android-NDK-r8d では
・armeabi
・armeabi-v7a
・MIPS
・x86
の4種類のCPUがサポートされています。
PowerPC系のAndroid端末が普及しない限りマルチプラットフォームの心配はないようです。
そこで、 前回 公開したOpenGLによる簡易画像ビュアーをAndroid-NDKに移植してみました。

Android-NDKの弱点
アプリケーションのresフォルダーに保存された画像や音声ファイルを直接読み込む方法がありません。
SDカードに保存された画像ファイルなら読み込むことはできますが、画像をテクスチャに表示するためには画像ファイルをBitmap(1次元配列)にデコードする必要があります。
ところがAndroid-NDKには画像ファイルをデコードするライブラリーが見当たりません。
Android-NDKで画像を扱うには次の選択肢があります。

1. AndroidのJavaのAPIで画像ファイルをデコードしたint配列をJNIに渡す。
2. 画像ファイルをデコードする処理をC/C++で自作する。
3. C言語で書かれたオープンソースの画像ローダーを利用する。

デバッグのしやすさから1番目の方法で画像ファイルをNDKで扱うことにします。

留意点
Android端末の機種によりますが、ビットマップ画像の扱い中にOutOfMemoryErrorが起きやすいです。
SH-03C(Android2.2)は 1440x1440ピクセルの画像を int配列(約8MB)にバッファーしようとすると必ず次のエラーが発生します。
Out of memory on a 8294416-byte allocation.
試行錯誤した結果、今回は次のような仕様にしました。

1. Javaで画像ファイルを読み込み、512×512に伸縮する。
2. 伸縮した画像をint配列に変換しJNIに渡す。
3. JNIのOpenGL APIで画像をテクスチャとして表示する。

このブログを書いている時点の開発環境は次の通りです。
・Windows8 (64bit)
・Eclipse Juno (32bit) (XP互換モードで起動)
・Android SDK r21.0.1
・Cygwin
・Android-NDK-r8d
※Android-NDKのビルド方法は環境に強く依存するため省略します。

2点以上のタッチ操作が必要なので、Android2.2以降でマルチタッチ対応の端末が必要です。
新品で発売されているAndroid端末なら、中華Padも含めてほぼど対応していると思います。

以下ソースです。

MainActivity.java
jni.cpp
glu.h (Android-NDKのsampleの com.example.SanAngeles から抜粋しました)
Android.mk
jni.cpp、glu.h、Android.mk はプロジェクトにjniというフォルダーを追加して、そこにコピーします。
※特別な権限(Permission)は不要なのでマニフェストは省略します。
Android2.2以降で動作します。
Target SDK Version が8以上の設定でビルドできます。
Android-NDKのビルド方法は環境に強く依存するので省略させて頂きます。

留意点でも書きましたが、古いスマートフォン(Android2.2以前)で実際に使ってみると 前回のJavaだけで作ったアプリに比べて
java.lang.OutOfMemoryError: bitmap size exceeds VM budget
が起きやすいです。
画像をint配列に変換するためのメモリーを確保したり、その逆の変換をするためのメモリーを確保したりするためメモリーの空き領域が不足がちになるようです。
さらにJavaだけで書いたアプリと体感速度を比べるても差がありませんでした。
当初の予想とは裏腹にデメリットの方が多かったのでタイトルに「失敗談」と付けました。

Android4.0なら安定して動作しますが体感速度は変わりません。

関連ブログ
[Android] BitmapクラスのOutOfMemoryErrorを防ぐ
[Android] BitmapクラスのOutOfMemoryErrorを防ぐ #2
[Android] フリーサイズの画像をOpenGLのテクスチャに表示する
[Android] OpenGLで簡易画像ビュアーを作る
[Android] ジェスチャーでOpenGL簡易画像ビュアーに拡大縮小機能を追加する
[Android] OpenGLでプロ生ちゃんをアニメーションさせる
[Android] OpenGL ESで文字を表示する
[Android] OpenGLで頂点の多いポリゴンを扱うには
[Android] OpenGLでシャープ製端末用3D(立体視)アプリケーションを作る
[Blender] obj2opengl.plをJava用に改造する
[Windows8][Android] Can't bind to local 8600 for debugger


以上、参考になれば幸いです。

2012年8月25日土曜日

[Android] ONDA Vi30はThumbモードとARMモードのどちらが速いのか?

Which is faster,m Thumb mode or ARM mode (ONDA Vi30)
以前のブログ
[Android] ThumbモードとARMモード、どちらが速いのか?
では必ずしもARMモードが速いわけではないことが分かりました。

ところで、先日購入したONDA Vi30のCPUはCortex A9互換のAML8726-MXとされています。
ONDAのページからAML8726-MXのアーキテクチャーを見ることができます。
ONDA Vi30のRAMはDDR3とのことですが、どちらが速いのか試してみました。

結果

Thumbモード ARMモード
(1)int型(32ビット)の検証 387ms 321ms
(2)float型(64ビット)の検証 164ms 144ms
(3)atan2関数(複雑な計算)の検証 3903ms 2847ms

ARMモードのほうが速いという結果になりました。


以上、参考になれば幸いです。

関連ブログ
[Android] ONDA Vi30 双核版を買いました
[Android] ONDA Vi30 双核版のファームウェア更新、トラブルシューティング、バッテリー改善など

2011年9月10日土曜日

[Android-NDK] ERROR [binderDied] end

How to solve "[binderDied] end" error

アプリを開発していたら、突然こんなエラーが起こりました。
ERROR/CameraService(1215): [binderDied] end

Android-NDKのログにはこんなエラーが出てます。
DEBUG/ndk(2474): [ 08-27 20:12:59.451 2474:0x9aa F//system/bin/app_process ]
DEBUG/ndk(2474): stack corruption detected: aborted

原因はJNI(Android-NDK)のchar配列の要素不足でした。

エラーになったコードの抜粋
sprintf関数の引数xとyとzがdouble型だったため、文字列に変換すると予想以上に長くなり、50バイトを超えてしまいました。
char c[50];を
char c[100];に変更したら正常に動きました。

LogCatに「CameraService」とあるし実際に android.hardware.Camera を使うアプリだったのですが、カメラは全く関係ありませんでした。
エラー内容と関係ないログが出力されたので、少し手間取りました。

ちなみにVisual C++ 2010 ではどんなエラーメッセージが出るのかと思い、同じバグを再現したところ
Run-Time Check Failure #2 - Stack around the variable '変数名' was corrupted.
バッファー オーバーランが *****.exe で発生し、プログラムの内部状態を破損しました。[中断] をクリックしてプログラムをデバッグするか、または [続行] をクリックしてプログラムを終了してください。
と表示されました。

「[binderDied] end」というメッセージはわかりにくいですが、「stack」と「corruption / corrupted」というキーワードを見たら、スタック領域の破損∋配列の要素不足の疑いがありそうです。

以上、参考になれば幸いです。

2011年8月20日土曜日

[Android] ThumbモードとARMモード、どちらが速いのか?

Which is faster, Thumb or ARM?

多くのAndroid端末に使われているARM系CPUは16ビットのThumbモードと32ビットのARMモードとがあります。
「ARMモードの方が速い」という意見がある一方、「Thumbモードはプログラムサイズが小さい分メモリーアクセスが少ない」という意見があり、どちらが効率がいいのかよくわかりません。
そこで、ThumbモードとARMモードを比較してみました。

Activityのソース(Main.java)
jni/nck.cpp
Android.mk(Thumbモードの場合)
Android.mk(ARMモードの場合)
結果
(1)int型(32ビット)の検証
エミュレーター・実機(IS01)とも、Thumbモードの方が速い。

(2)float型(64ビット)の検証
エミュレーターではARMモードの方が速く、実機(IS01)ではthumbモードの方が速い。

(3)atan2関数(複雑な計算)の検証
エミュレーターではARMモードの方が速く、実機(IS01)ではthumbモードの方が速い。

結論
Thumbモードの方が速い場合がある。
ARMモードが常に速いとは限らないようです。Android-NDKを使ったアプリケーションを公開する時は機種ごと・アプリごとにベンチマークを取って比較した方がいいようです。

以上、参考になれば幸いです。

2011年8月6日土曜日

[Android] Android-NDKでテクスチャを表示するには

How to draw textures in Android-NDK

Havaは大きいソースが扱えないので、[Android] 頂点の多いポリゴンを扱うには では頂点数の多いポリゴンをAndroid-NDKを使ってJNIからJavaに大きい配列を渡す方法でバナナを表示しました。この方法はFloatBufferの作成に時間がかかるという問題がありました。
今回は、頂点とテクスチャの機能もJNIで書いてみます。

JNIで画像を扱うには?
テクスチャを表示するためglTexImage2Dを使います。
glTexImage2Dで表示できるテクスチャ画像はunsigned char型配列のビットマップデータです。配列の内容は1ピクセルごとにRGBAの順に1バイトずつです。
このブログを作成している時点ではJNIからres/drawableフォルダーやassetsフォルダーのファイルを扱う方法が見当たりませんでした。
そこで、JNIで画像データを扱うために次のようにしました。
  1. Javaでres/drawableフォルダーの画像をint型配列に変換してJNIに渡す
  2. JNIでJavaから渡されたint型配列をunsigned char型配列に変換しテクスチャ表示する
以下ソースです。
ndk.cpp
glu.h (Android-NDKのsampleの com.example.SanAngeles から抜粋しました)
Android.mk
これら ndk.cpp、glu.h、Android.mk と、HBehrens-obj2opengl-a0f123e.zipのbanana.h をプロジェクトのjniフォルダーにインポートし、カレントフォルダーをjniに移してndk-buildを実行します。
HBehrens-obj2opengl-a0f123e.zipののbanana.jpgをres/drawableフォルダーにインポートします。

Activityのソース(Main.java)
画面をフリックするとバナナが回転するようにしました。
これをエミュレーターで実行したら一瞬でバナナが表示されました。JavaでFloatBufferを作成する方法(エミュレーターで2分くらい)とは大違いの速さです。
テスト環境では、Heapを見比べたらJavaでFloatBufferを作成する方法に比べて1MBほどメモリーの節約になりました。
Android-NDKでビルドしたアプリケーションはARMの端末でしか動作しないのが玉に瑕です。

以上、参考になれば幸いです。