ブログランキング・にほんブログ村へ


iPhone/iPad用潜水艦ゲームアプリ ソナーエコー iTunesにて公開中

2013年06月03日

[Android NDK]複数のsoのAndroid.mkを作るときとか

AndroidのNDK。

Android.mkを使うのはいいけど、複数のAndroid.mkがあるときはどうすればいいか。

libjpegを自前でもったりするパターンで、

jni/jpeg-9
jni/mylib

みたいになってるとき。

これは

jniの直下に Android.mk を作って、

include $(call all-subdir-makefiles)

と書き、
各々のフォルダに Android.mkを置けばいいということらしい。

上の例では

jni/jpeg-9
jni/mylib
の2つにAndroid.mkを書いておくということだ。

ただし、その各々のAndroid.mkの頭に

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

と入れておかないと、直前の Android.mkが汚した変数とかカレントディレクトリが残ってておかしなことになるみたいだ。


あと、さらに加えて、so形式で供給される NDKライブラリがあるときはどうなるか。
普通なら

libs/armeabi
の下に xxxxx.so をただおけばいいのだが、上の Android.mkをやるとここの soファイルをビルドに関係ないものまで消してしまうようだ。

これは

jniフォルダの下にもう1つフォルダを増やし、

jni/external/lib

みたいにし、そこに xxxxx.soを置いて、

jni/externalに

Android.mkを書く。

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE := xxxxx
LOCAL_SRC_FILES := lib/xxxxx.so
include $(PREBUILT_SHARED_LIBRARY)

よくわからんけど、ようするにただファイルをコピーしろということのようだ。

これで ndk-buildすると xxxxx.soも libs/armeabi下にコピーされるようになる。



最後に、上とは無関係だが、パッケージ名やクラス名に '_'(アンダスコア)が含まれてしまっている場合。

これだと、ndkのexport関数名がおかしなことになってしまう。

com.example_a.*
パッケージの

aaa_bbb

クラスのmyfuncメソッドだとすると、

JNIEXPORT void JNICALL Java_com_example_a_main_aaa_bbb_myfunc

???
これだとセパレータの _ か元からの _ かわからないので実行時みつからないっていうエラー UnsatisfiedLinkError になってしまう。

こういう場合は、 '_'を'_1'でエスケープできる。

つまり、

JNIEXPORT void JNICALL Java_com_example_1a_main_aaa_1bbb_myfunc

これでok。


参考:

[ Android ] 自分でコンパイルした既存のビルド済みの複数の共有ライブラリ(lib***.so)を使う方法。 Android.mk の設定が必要

Android NDKでlibjpegをビルドして利用する

【Android】【NDK】JNIのパッケージ名、クラス名に_(アンダースコア)がある場合
posted by みこあいさ at 18:11| Android開発

2013年04月22日

HttpGetとURLConnectionのリクエストヘッダの違い

AndroidのJavaでHttp GETリクエストを投げる方法には
HttpGetを使う方法とURLConnectionを使う方法の2つがある。
たいていはどっちでも同じ結果になるので、慣れてるとか好みの方法を選ぶくらいでいいんじゃないかと思うが、たまに同じ結果にならない場合がある。

それはもちろんサーバ側の応答になにか仕掛けがあるからに違いないのだけど、それが何か調べてみるため両方でhttpリクエストをしてみて、phpの$_SERVER情報を出してみた。

HTTPGetの場合----------------------------------

PHPRC: /home/XXXXXXX/www
PATH: /usr/local/bin:/usr/bin:/bin
DOCUMENT_ROOT: /home/XXXXXX/www
HTTP_CONNECTION: Keep-Alive
HTTP_HOST: XXXXXX.sakura.ne.jp
HTTP_USER_AGENT: Apache-HttpClient/UNAVAILABLE (java 1.4)
REMOTE_ADDR: XXX.XX.XX.XXX
REMOTE_HOST: emXXX-XX-XX-XXX.emobile.ad.jp
REMOTE_PORT: 17151
SCRIPT_FILENAME: /home/XXXX/www/XXXXXXXXXXXXXXXXXXX
SERVER_ADDR: XXX.XX.XX.XXX
SERVER_ADMIN: XXXXXX@sakura.ad.jp
SERVER_NAME: XXXXXX.sakura.ne.jp
SERVER_PORT: 80
SERVER_SOFTWARE: Apache/1.3.42 (Unix) mod_ssl/2.8.31 OpenSSL/0.9.8e
GATEWAY_INTERFACE: CGI/1.1
SERVER_PROTOCOL: HTTP/1.1
REQUEST_METHOD: GET
QUERY_STRING: arg=XXXXXX
REQUEST_URI: /XXXX.php?arg=XXXXXX
SCRIPT_NAME: /XXXX.php
PHP_SELF: /XXXX.php
REQUEST_TIME: 1366106161
argv: Array
argc: 1

URLConnetionの場合-----------------------------

PHPRC: /home/XXXXXX/www
PATH: /usr/local/bin:/usr/bin:/bin
DOCUMENT_ROOT: /home/XXXXXX/www
HTTP_ACCEPT_ENCODING: gzip
HTTP_CONNECTION: Keep-Alive
HTTP_HOST: XXXXXX.sakura.ne.jp
HTTP_USER_AGENT: Dalvik/1.4.0 (Linux; U; Android 2.3.4; ISW11M Build/4.5.1A-1_KDI-95_MR3-10)
REMOTE_ADDR: XXX.XX.XX.XXX
REMOTE_HOST: emXXX-XX-XX-XXX.emobile.ad.jp
REMOTE_PORT: 33594
SCRIPT_FILENAME: /home/XXXXX/www/cs/sn/count.php
SERVER_ADDR: XXX.XX.XX.XXX
SERVER_ADMIN: XXXXXX@sakura.ad.jp
SERVER_NAME: XXXXX.sakura.ne.jp
SERVER_PORT: 80
SERVER_SOFTWARE: Apache/1.3.42 (Unix) mod_ssl/2.8.31 OpenSSL/0.9.8e
GATEWAY_INTERFACE: CGI/1.1
SERVER_PROTOCOL: HTTP/1.1
REQUEST_METHOD: GET
QUERY_STRING: arg=XXXXXX
REQUEST_URI: /XXXX.php?arg=XXXXXX
SCRIPT_NAME: /XXXX.php
PHP_SELF: /XXXX.php
REQUEST_TIME: 1366106037
argv: Array
argc: 1

----------------------------------------
こんな感じ。細かいところで違ってるが、一番大きいのはやはりというべきかAgent。
HttpGetだとJavaとして、URLConnectionだとAndroidとしてリクエストしてるって感じだ。

HttpGetの場合
HttpClientからHttpParamsを引き出して
setParameter(CoreProtocolPNames.USER_AGENT, "XXXXXXXXXXXXXXXX" );
でエージェントをセットしてやることはできるので、それで用が足りるならそれもよし。
posted by みこあいさ at 15:49| Android開発

2013年04月01日

HttpClientでlocation redirectが自動で実行されないようにする

Android。

HttpPostやHttpGetをHttpClientにかませてHTTPサーバーにリクエストを投げてHttpResponseを受けるパターン。


HttpClient httpclient = new DefaultHttpClient();

そのまんまだと、リダイレクトが勝手に処理されて、得られるHttpResponseはリダイレクトした先のものになってしまう。

そういうときは
httpclient.getParams().setBooleanParameter(ClientPNames.HANDLE_REDIRECTS,false );

とやって自動リダイレクトを抑止してやる必要があるらしい(実験検証図済み、ただしAndroid2.3えみゅ)。


んで、
HttpResponse httpResponse = httpclient.execute(httpPost);

とかして得られたレスポンスから、location指定されたリダイレクト先を得る。

Header[] sHeaders = httpResponse.getHeaders( "location" );
if( sHeaders != null && sHeaders.length > 0 ){
String locationUrl = sHeaders[ 0 ].getValue();
Log.v("location url", locationUrl );
}

この例は単にLogに出してるだけだけど。

あと、locationでリダイレクト指定されたときのhttpのステータスって200 OKじゃなくって 302 Moved Temporarily になるの、いまさらながら知った。

##2013.4.22追記

.htaccessの
RewriteEngine on
でリダイレクトすると
301 リダイレクトってのになる。
posted by みこあいさ at 18:43| Android開発