× [PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。 |
以下の記述はセットで機能する。
import-add-path に書かれたパスから、 import-module に書かれたディレクトリ下のAndroid.mkをインポートする。 上記だと、 cocos2d/external/Box2D/Android.mk cocos2d/extensions/Android.mk などがインポートされることになる。 それぞれのAndroid.mkにもまた 読み込むソースファイルやモジュール、ライブラリが記述してあるわけだ LOCAL_WHOLE_STATIC_LIBRARIES リンカの–whole-archiveオプションのこと。 これを指定した静的ライブラリは、ライブラリ全体が実行ファイルに含まれることになる(必要な部分だけをstripするということをしなくなる) 参考 最新のcocos2d-xのデフォルトプロジェクトでは、この指定はなくなっている PR |
iOS版はすでに動いている
cocos2d-x バージョン3.7 AndroidStudio バージョン1.3 (作業中に1.5.1にアップデート) AndroidStudioに対応したcocos2d-xのバージョンだと、プロジェクトのディレクトリに proj.android-studio/ が作られている。 まずはAndroidStudioを開いてみる ディレクトリは前述の場所を選択。 すると以下のエラーが出た どうやらJDKの指定が悪い様子。 JDKのパスを確認する方法は を選択。 すると以下のような画面になる 下部にエラー内容が書いてある。 "Please choose a valid JDK directory." つまり、以下のパスを修正しろということだ /System/Library/Java/JavaVirtualMachine/1.6.0.jdk/Contents/Home このパスが間違っているわけではないはずなのだが(Eclipseの時はこれで動いていたので) 変えた方が良さそうだ。 ひとまずjdkの最新をダウンロードしてみる。 ダウンロードページ ダウンロードされた場所は以下。 /Library/Java/JavaVirtualMachines/jdk1.8.0_73.jdk/Contents/Home このパスを指定すると、エラーが消えた。 ついでに、Android SDK のパスも変更。 adt-bundle-mac-x86_64-20140321 になっているが、昔のeclipseのダウンロードした時のままなのであまりふさわしくない (中にAPI level別のディレクトリが入っているし) 変更。 この場合、 ~/.bash_profile の中身の ANDROID_SDK_ROOT を書き換え、 $ source ~/.bash_profile を実行する。 また、ポップアップに従って、AndroidStudioをアップデートした。 次に、 Android.mkの指定をする必要がある。 LOCAL_SRC_FILESの部分は変更が必須。 Classesディレクトリ以下のすべての.cppと.hを正しくビルドに含めるために、以下のように記述。
また、AndroidStudioからディレクトリ階層が一つ深くなっているので、そこも変更 なおこのコマンドが実行される時のカレントディレクトリ(Android.mkのある場所)は proj.android-studio/app/jni/ である。 これでビルドしてみる。
コンパイルして実行もする場合は以下のように
ANDROID PLATFORM(android SDK バージョン)を、AndroidStudioで使用しているのと違うものを指定したい場合は、ap オプションで指定できる
が、エラーが結構出る。 特に困るのが、stringクラスが使えないこと。 error: 'to_string' is not a member of 'std' みたいな。 NDKのSTLに含まれていないらしい。なんと不便な to_stringだけなら自前実装もできるが、stolとか軒並み駄目なので、なんとかしたい。 Application.mkの先頭行を
から
に書き換えると、できるようになる。 参考ページ 指定できるライブラリ一覧 ライブラリを追加する方法は で選択。 決定すると、自動でダウンロード、ビルドされる。 また、build.gradleにも自動で書き込まれている。 しかし、これもエラーが。 No resource found the matches the given name 'android:TextAppearance.Material.Widget.Button.Inverse' 原因は、APIレベルがあっていないことらしい 以下の対応をしたら直った ・Project Structureウィザードで、プロジェクトのBuildToolVersionを23.0以上にする ・build.gradleに以下を記述 compile 'com.android.support:support-v4:23.1.1' 参考 これらを対応してようやっとビルドに成功。 しかしまだ気になるワーニングがある
Project Structureを見ると、ご丁寧にNDKのダウンロードができるようになっている。 クリックして、ダウンロードする(10分ほどかかる) すると、自動的にディレクトリがセットされる (ダウンロードディレクトリは、ANDROID_SDK_ROOT/ndk-bundle になる) このディレクトリをbash_profileのNDK_ROOTに書き、 $ source ~/.bash_profile を実行すれば、ワーニングは消えた |
以前admobから告知があった(そして本社に行った)、
アプリ内課金と広告をユーザに応じて出しわける例の技術。 名前は「アプリ内課金向け広告」というらしいが。 公式 現時点でまだベータ版なのと、 Android版だけのサービスなので(GooglePlayで検索して出てくるアプリにしか使えないと明記されている)、とりあえず実装は見送り |
後から思い出しながらなので、抜けがあるかもしれないが。
なお結論としては、直接Macとつないでのデバッグは不可。ログを見たりはできない。 ネットワークからapkをダウンロードして動作確認しかできない。 1. 端末を初期化して、Gmailアカウントを設定。 このアカウントは、テスト用(主に課金テスト)に使う物。 自分の普段使うアカウントではない。 2. 設定アプリ→端末情報→ソフトウェア情報→ビルド番号を連打。これで開発者オプションを有効にする 3. 設定アプリ→PC接続→USB接続方法の選択→充電(気持ち的にはテザリングのような気がするが) 4. http://www.lg.com/jp/support-mobile/lg-D620J からUSBドライバーをインストール。再起動 5. USBケーブルで繋いだら、あとは出来る はずだったのだが、ドライバーがMac OS 10.11 (El Capitan)に対応していない! そのため $ adb devices で表示されない… $ adb install XXX.apk ももちろんできない… ○繋いでいるはずのandroid端末がadbから見えない時の対処 ここからは、以下のページを見てやってみる 参考ページ まずは端末をmacに繋ぐ 左上のリンゴ→このMacについて→システムレポートをクリック USBの項目を見る ここの、製造元ID(Vendor ID)をチェック。 この16進数を、以下のファイルに書き込む $ echo 0x1001 >> ~/.android/adb_usb.ini これで、adbを再起動し、再度チェック $ adb kill-server $ adb devices これで出る! はずだが、やはり出なかった ドライバーが古いせいなのか… |
jarファイルはこの位置に書く
|
Android Studioを導入。
ずっとEclipse+ADTでやってきたが、これを機にやっとこさAndroidStudioに入る。 こういうきっかけがないとなかなか始めない(今まで作ってきたゲームの改良続きだと、環境を変えないでも十分すぐに作れてしまうし) というわけでまずはダウンロード。 パッケージが展開されるところまでは問題ないだろう。 Android Studioを起動するとWelcome画面になる。 今回は、gradleを使用したサンプルプロジェクトが用意されていたので、 以下のように、gradleプロジェクトをインポートする。 選択するディレクトリはココ。 appやgradleディレクトリ、settings.gradleの1つ上。 すると、こんな感じでプロジェクトが開く。 ちなみに赤丸囲みのところ、初めは「Android」になっているが、 「Project」に変えておくと、実際のディレクトリ構造と同じように表示される。慣れるまではこちらのほうがよさそうだ。ディレクトリ追加などもここからできるようになる。 さて、さっそくビルドしようとすると(というかバックグラウンドで勝手にビルドしてる) いくつかエラーが発生。 うむ。SDKのandroid-22がないと。 リンクを踏むと、勝手にインストールし始める。 簡単だ! Eclipseのときとは大違い。 再度ビルドするが、またエラー。 なるほど。ツールのほうもないと。 ではリンクを踏みましょう。 で完了。 うう〜ん、べんり! こんな感じで、エラーを解決させていけば、ビルドできた。 ちなみに、ビルド設定などは build.gradle に書く。 依存関係など。 見て分かるように、SDKバージョンもbuild.gradleに書くようになっている。 AndroidManifest.xml には書かない! とりあえず、いろいろ分かりやすくなっているぞ! |
Androidで、ビューをpx指定で表示したいことがある。
当たり前のやり方のような気がするが、意外と方法が用意されていない。 iOSなら、view.frameやview.boundsで矩形を指定することができるのだが、Androidはそれがない。 Androidは、ビューに加えて、レイアウト(FrameLayout,LinearLayout,RelativeLayoutなど)という概念がある。 (正確にはレイアウトもビューなのだが。) ビューはレイアウトの中に配置される。 そのビューを、レイアウトから上下左右のマージンいくつ離すか、という指定をすることになる。 本来これでいいはずなのだが、 実際にビューを配置してみると、狙った位置と大きさも位置もずれていることがある。 なぜか。 マージンを指定することによって、矩形の大きさが決まる。 例えば、幅640,高さ240のLayoutの中に、左右マージン各20,上下マージン各10を取ると、 ビューのRect(x,y,w,h)=(20,10,600,220)になる。 しかし、ビューが実際に正確にその大きさで配置されるとは限らない。 たとえば、ビューの幅、高さの指定がWRAP_CONTENTだと、矩形のサイズはあまり関係なくビューの「見た目の大きさ」は決まってしまう。 また、MATCH_PARENTだとしても、 たとえばImageViewなら、元画像の縦横比を崩さない範囲で最大サイズ表示、のようなことになるからだ。 また、広告SDKで表示するアイコンなど、実際の表示サイズが不定になるものの場合もある。 そのようなとき、ビューは大抵左上寄せの位置に表示される。 これは嫌だ。指定座標を中心とする位置に収まってほしい。 じゃあ、gravityをCENTERに指定すれば…? としたいが、gravity指定はビューにはできず、Layoutに指定する。 gravityは、そのレイアウト全体の重力場を指定するためのものだからだ。 ビューを中央寄せにする指定をビュー自体に対してできないか…となる。 もちろんその指定はあって、xmlでいうと centerHorizontal などの指定がそれにあたる。これは、 「自分の親のレイアウトの左右方向中心に配置」 ということだ。 ……ということは、自分の親のレイアウトが必要になる。 何も考えずそのままcenterHorizontal,centerVerticalを指定したら、大本のレイアウト(おそらく画面全体を覆うRelativeLayoutになっているだろう)の中心に行ってしまう。それはスクリーンの中心だ。 そうじゃない。 さっき指定した矩形の中心にいてほしいのだ! …………ということは、さっきの指定の矩形のレイアウトを作成すればいいんだ。
という二重構造にすればよい。
こういう感じになる。 中間レイアウトはRelativeLayoutでなければダメで、他のレイアウトだとマージン指定が効かない。 FrameLayoutやLinearLayoutにすると表示位置が左上固定になってしまう。 RelativeLayoutなので、レイアウトパラメータもRelativeLayout.LayoutParamsにする。 ビューのレイアウトパラメータもRelativeLayout.LayoutParamsにする。 でないとaddRule()メソッドが使えない。(だからCENTER_HORIZONTAL/VERTICAL指定ができない) FrameLayoutには lp2.gravity = Gravity.CENTER; のような指定もできるが、これは自分の子孫に対して効かせるパラメータなので、ビュー自身を中央寄せしたい場合は意味が無い。 というわけで、 ================================= 中間レイアウトはRelativeLayout 中間レイアウトのパラメータはRelativeLayout.LayoutParams ビューのパラメータもRelativeLayout.LayoutParams ================================= となる。 ちなみにレイアウトパラメータ類の子孫関係は以下
どのレイアウトパラメータも、コンストラクタの基本はwidthとheightの指定(int)である。 lp1のように、幅と高さを直に設定することもできるが、 多くの場合はlp2のように MATCH_PARENT(-1) か WRAP_CONTENT(-2) という特殊な値を入れて使うことになる。 |
こんな感じ。
AndroidManifest.xmlには
と記述のこと。 ◯内部クラスを使う場合の注意 ・内部クラスはstaticをつけて定義する Javaでは、内部クラスは基本的にstaticをつけて宣言することが推奨。 staticにしていないと、「no empty constructor」という実行時エラーになる。 なぜなら、staticでない内部クラスは、それを包含するクラスからしかインスタンス化できないからだ。 ちなみに、staticでない内部クラスは、自身を包含するクラスへの参照を暗黙的に持つ。アクセスできて便利だが、当然gcを阻害することになる ・AndroidManifest.xmlでは、内部クラスは $ で繋ぐ。 これもJava的な決まり事。 |
JNIで
というエラーが出た。 ググってみると、無効になったクラスにアクセスしてるとか、解放された変数に参照しているみたいなことが書いてある。 参考 参考 でも、そんな単純ミスはしていない。 おかしい。 その少し前のワーニングで、 trying to work around app JNI bugs, but didn't find 0xXXXXXXXX in table! DeleteLocalRef(0xXXXXXXXX) failed to find entry というようなのが出ている。 で、このポインタが示す変数はなんぞや、というのを出力して見てみたところ、 C++変数から変換したJNIオブジェクトだった。 特に何の問題もなさそう。 さらに発見したのが、
の戻り値のobjResultが0x1になっている。 エラーはこの変数にアクセスした瞬間起きたようだ。 しかし、メソッドシグネチャーも合っているし、なぜ戻り値がこんなことになるのか。 このコードのどこに問題があるのか。 こういう不可解なことが起きるときはスレッドが絡んでいるもの。 そうすると真の原因はここでないまったく別の場所にある可能性がある。 ということで、ともかく例外を出力させてみる。
すると…
案の定、スレッドのエラーだった。 発生箇所とはこことは無関係の場所。 ここを直したら、無事に動いた。 |
以下のようにして例外を出力できる
また、ポインタ変数を確認したいときは以下のようにすればよい。
辿ってみるとわかるが、jstringとかjobjectは全部 _jobject クラスの子孫になっている。 |