Android用にMonoをbuildする
AndroidでスタンドアロンのMonoを使いたかったのでMonoをbuildしました。
その手順を忘れないように書いておきます。
対象となるMonoのバージョンは2.10.5です。
2.10.5の理由は手元のUbuntuのapt-getでinstallされたのが2.10.5だったからです。
以下の手順でbuildを行います。
- Androidのソースツリーを取得
- externalの下に「androidmono」という名前でディレクトリを作成
- external/androidmonoの中でgit cloneなりtarを展開するなりしてMonoのソースを展開
- 展開したMonoのディレクトリを「mono」という名前に変更
- Android.mkとApplication.mkを作成
- パッチを適用する
- ビルドに必要なヘッダファイル群を展開する
という感じです。
Android.mkの中身はこんな感じですね。
LOCAL_PATH := $(call my-dir) MONO_PATH := $(LOCAL_PATH)/mono MONO_ASSEMBLY_DIR := \"/data/local/mono/lib/\" MONO_CONFIG_DIR := \"/data/local/mono/bin/\" MONO_BINARY_DIR := \"/data/local/mono/bin/\" MONO_CFLAGS := -DMONO_ASSEMBLIES=$(MONO_ASSEMBLY_DIR) \ -DMONO_CFG_DIR=$(MONO_CONFIG_DIR) \ -DMONO_BINDIR=$(MONO_BINARY_DIR) \ -DHAVE_CONFIG_H -DARM_FPU_VFP -D_REENTRANT \ -DPAGE_SIZE=4096 -DS_IWRITE=S_IWUSR \ -DPLATFORM_ANDROID -D__linux__ -DREDIRECT_MALLOC=GC_malloc \ -DHAVE_BOEHM_GC -DHAVE_GC_H -DUSE_INCLUDED_LIBGC -DHAVE_GC_GCJ_MALLOC -DHAVE_GC_ENABLE \ -D_GNU_SOURCE -DUSE_MMAP -DUSE_MUNMAP -D_FILE_OFFSET_BITS=64 -DNO_UNALIGNED_ACCESS \ -D__environ=environ MONO_LIBGC_CFLAGS := -DPACKAGE_NAME=\"libgc-mono\" -DPACKAGE_VERSION=\"6.6\" -DPACKAGE_STRING=\"libgc-mono\ 6.6\" \ -DGC_LINUX_THREADS=1 -D_REENTRANT=1 \ -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 \ -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_UNISTD_H=1 -DHAVE_DLFCN_H=1 \ -DLT_OBJDIR=\".libs/\" -DSILENT=1 -DNO_SIGNALS=1 -DNO_EXECUTE_PERMISSION=1 \ -DGC_GCJ_SUPPORT=1 -DJAVA_FINALIZATION=1 -DATOMIC_UNCOLLECTABLE=1 -D_IN_LIBGC=1 \ MONO_INCLUDES := $(MONO_PATH)/ \ $(MONO_PATH)/mono/ \ $(MONO_PATH)/eglib/src/ \ $(MONO_PATH)/mono/mini/ \ $(MONO_PATH)/libgc/include \ $(LOCAL_PATH)/configs \ $(LOCAL_PATH)/configs/eglib \ $(LOCAL_PATH)/configs/mono/mini \ $(LOCAL_PATH)/configs/mono/arch/arm \ bionic/linker MONO_LDLIBS := -ldl # build 'libeglib' include $(CLEAR_VARS) LOCAL_MODULE := eglib LOCAL_MODULE_TAGS := eng LOCAL_PATH := $(MONO_PATH)/eglib/src LOCAL_SRC_FILES := garray.c gerror.c ghashtable.c gmem.c goutput.c \ gstr.c gslist.c gstring.c gptrarray.c glist.c gqueue.c gpath.c \ gshell.c gspawn.c gfile.c gfile-posix.c gpattern.c gmarkup.c \ gutf8.c gunicode.c gdate-unix.c gdir-unix.c gfile-unix.c \ gmisc-unix.c gmodule-unix.c gtimer-unix.c LOCAL_CFLAGS := $(MONO_CFLAGS) LOCAL_C_INCLUDES := $(MONO_INCLUDES) include $(BUILD_STATIC_LIBRARY) # build 'libmonoutils' include $(CLEAR_VARS) LOCAL_ARM_MODE := arm LOCAL_MODULE := monoutils LOCAL_MODULE_TAGS := eng LOCAL_PATH := $(MONO_PATH)/mono/utils LOCAL_SRC_FILES := mono-semaphore.c mono-md5.c \ mono-sha1.c mono-logger.c mono-codeman.c dlmalloc.h dlmalloc.c \ mono-counters.c mono-compiler.h mono-dl.c mono-dl.h \ mono-internal-hash.c mono-internal-hash.h \ mono-io-portability.c mono-io-portability.h monobitset.c \ mono-math.c mono-mmap.c mono-mmap.h mono-proclib.c \ mono-proclib.h mono-time.c mono-time.h strtod.h strtod.c \ strenc.h strenc.c mono-uri.c mono-poll.c mono-path.c \ mono-stdlib.c mono-property-hash.h mono-property-hash.c \ mono-value-hash.h mono-value-hash.c freebsd-elf_common.h \ freebsd-elf32.h freebsd-elf64.h freebsd-dwarf.h dtrace.h \ mono-filemap.c mono-networkinterfaces.c mono-error.c \ mono-publib.c LOCAL_CFLAGS := $(MONO_CFLAGS) LOCAL_C_INCLUDES := $(MONO_INCLUDES) LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -ldl include $(BUILD_STATIC_LIBRARY) # build 'libmonoruntime' include $(CLEAR_VARS) LOCAL_ARM_MODE := arm LOCAL_MODULE := monoruntime LOCAL_PATH := $(MONO_PATH)/mono/metadata LOCAL_SRC_FILES := runtime.c \ mono-basic-block.c mono-wsq.c mono-hash.c reflection.c object.c object-internals.h \ icall.c icall-def.h char-conversions.h decimal.c decimal.h \ boehm-gc.c sgen-gc.c sgen-gc.h gc.c gc-internal.h method-builder.h method-builder.c \ mono-mlist.c mono-mlist.h tabledefs.h threads-types.h threadpool-internals.h \ file-io.c file-io.h socket-io.c socket-io.h exception.c exception.h \ debug-mono-symfile.h debug-mono-symfile.c mono-debug.h mono-debug.c \ mono-debug-debugger.h mono-debug-debugger.c profiler-private.h attach.h attach.c \ rand.h rand.c security.c security.h security-core-clr.c security-core-clr.h \ string-icalls.c string-icalls.h sysmath.h sysmath.c process.c process.h \ environment.c environment.h locales.c locales.h normalization-tables.h \ filewatcher.c filewatcher.h culture-info.h culture-info-tables.h \ security-manager.c security-manager.h console-io.h console-unix.c \ coree.c coree.h domain.c domain-internals.h opcodes.c cil-coff.h \ metadata.c metadata-internals.h number-formatter.h verify.c verify-internals.h \ mono-endian.c mono-endian.h mono-config.c loader.c \ class.c class-internals.h wrapper-types.h mempool.c \ mono-perfcounters.c mono-perfcounters.h mono-perfcounters-def.h \ debug-helpers.c mempool-internals.h metadata-verify.c \ mono-cq.c LOCAL_CFLAGS := $(MONO_CFLAGS) LOCAL_C_INCLUDES := $(MONO_INCLUDES) include $(BUILD_STATIC_LIBRARY) # build 'libmonoruntimearm' include $(CLEAR_VARS) LOCAL_ARM_MODE := arm LOCAL_MODULE := monoruntimearm LOCAL_MODULE_TAGS := eng LOCAL_PATH := $(MONO_PATH)/mono/metadata LOCAL_SRC_FILES := \ monitor.c marshal.c threadpool.c threads.c appdomain.c \ profiler.c cominterop.c assembly.c image.c null-gc.c LOCAL_CFLAGS := $(MONO_CFLAGS) LOCAL_C_INCLUDES := $(MONO_INCLUDES) include $(BUILD_STATIC_LIBRARY) # build 'libwapi' include $(CLEAR_VARS) LOCAL_ARM_MODE := arm LOCAL_MODULE := wapi LOCAL_MODULE_TAGS := eng LOCAL_PATH := $(MONO_PATH)/mono/io-layer LOCAL_SRC_FILES := access.h atomic.c atomic.h \ collection.h context.c context.h critical-sections.c \ critical-sections.h critical-section-private.h error.c error.h \ events.c events.h event-private.h handles.h \ handles-private.h io.h io-portability.c io-portability.h \ io-private.h io-layer.h macros.h messages.c messages.h misc.c \ misc-private.h mutexes.c mutexes.h mutex-private.h \ mono-mutex.c mono-mutex.h mono-spinlock.h processes.c \ processes.h process-private.h security.c security.h \ semaphores.c semaphores.h semaphore-private.h shared.c \ shared.h sockets.c sockets.h socket-private.h \ socket-wrappers.h status.h system.c system.h \ threads.h thread-private.h timefuncs.c timefuncs.h \ timefuncs-private.h types.h uglify.h versioninfo.c \ versioninfo.h wait.c wait.h wapi_glob.h wapi_glob.c locking.c posix.c LOCAL_CFLAGS := $(MONO_CFLAGS) LOCAL_C_INCLUDES := $(MONO_INCLUDES) include $(BUILD_STATIC_LIBRARY) # build 'libwapiarm' include $(CLEAR_VARS) LOCAL_ARM_MODE := arm LOCAL_MODULE := wapiarm LOCAL_MODULE_TAG := eng LOCAL_PATH := $(MONO_PATH)/mono/io-layer LOCAL_SRC_FILES := collection.c io.c wthreads.c handles.c LOCAL_CFLAGS := $(MONO_CFLAGS) LOCAL_C_INCLUDES := $(MONO_INCLUDES) include $(BUILD_STATIC_LIBRARY) # build 'libgc' include $(CLEAR_VARS) LOCAL_ARM_MODE := arm LOCAL_MODULE := gc LOCAL_MODULE_TAG := eng LOCAL_PATH := $(MONO_PATH)/libgc LOCAL_SRC_FILES := allchblk.c blacklst.c \ checksums.c dyn_load.c \ headers.c mark.c \ new_hblk.c pcr_interface.c \ ptr_chck.c real_malloc.c solaris_pthreads.c \ solaris_threads.c specific.c stubborn.c backgraph.c \ win32_threads.c pthread_stop_world.c \ darwin_stop_world.c mach_dep.c LOCAL_CFLAGS := $(MONO_CFLAGS) $(MONO_LIBGC_CFLAGS) LOCAL_C_INCLUDES := $(MONO_INCLUDES) include $(BUILD_STATIC_LIBRARY) # build 'libgcarm' include $(CLEAR_VARS) LOCAL_ARM_MODE := arm LOCAL_MODULE := gcarm LOCAL_MODULE_TAG := eng LOCAL_PATH := $(MONO_PATH)/libgc LOCAL_SRC_FILES := alloc.c dbg_mlc.c finalize.c gc_dlopen.c gcj_mlc.c malloc.c \ mallocx.c mark_rts.c obj_map.c os_dep.c misc.c reclaim.c pthread_support.c typd_mlc.c LOCAL_CFLAGS := $(MONO_CFLAGS) $(MONO_LIBGC_CFLAGS) LOCAL_C_INCLUDES := $(MONO_INCLUDES) include $(BUILD_STATIC_LIBRARY) # build 'libmini' include $(CLEAR_VARS) LOCAL_ARM_MODE := arm LOCAL_MODULE := mini LOCAL_MODULE_TAG := eng LOCAL_PATH := $(MONO_PATH)/mono/mini LOCAL_SRC_FILES := mini.c method-to-ir.c \ xdebug.c decompose.c \ jit-icalls.c trace.c \ mini-arch.h dominators.c cfold.c regalloc.c \ helpers.c liveness.c ssa.c abcremoval.c ssapre.c \ local-propagation.c driver.c debug-mini.c \ linear-scan.c aot-runtime.c \ graph.c mini-exceptions.c mini-codegen.c mini-trampolines.c \ declsec.c wapihandles.c branch-opts.c \ mini-generic-sharing.c regalloc2.c simd-intrinsics.c \ unwind.h unwind.c mini-posix.c \ mini-arm.c exceptions-arm.c tramp-arm.c image-writer.c \ dwarfwriter.c mini-gc.c LOCAL_CFLAGS := $(MONO_CFLAGS) LOCAL_C_INCLUDES := $(MONO_INCLUDES) include $(BUILD_STATIC_LIBRARY) # build 'libminiarm' include $(CLEAR_VARS) LOCAL_ARM_MODE := arm LOCAL_MODULE := miniarm LOCAL_MODULE_TAG := eng LOCAL_PATH := $(MONO_PATH)/mono/mini LOCAL_SRC_FILES := aot-compiler.c debugger-agent.c LOCAL_CFLAGS := $(MONO_CFLAGS) LOCAL_C_INCLUDES := $(MONO_INCLUDES) include $(BUILD_STATIC_LIBRARY) # build 'libmono' include $(CLEAR_VARS) LOCAL_ARM_MODE := arm LOCAL_MODULE := libmono LOCAL_MODULE_TAGS := eng LOCAL_PATH := $(MONO_PATH)/mono/mini LOCAL_SRC_FILES := mini.c method-to-ir.c \ xdebug.c decompose.c \ jit-icalls.c trace.c \ mini-arch.h dominators.c cfold.c regalloc.c \ helpers.c liveness.c ssa.c abcremoval.c ssapre.c \ local-propagation.c driver.c debug-mini.c \ linear-scan.c aot-runtime.c \ graph.c mini-exceptions.c mini-codegen.c mini-trampolines.c \ declsec.c wapihandles.c branch-opts.c \ mini-generic-sharing.c regalloc2.c simd-intrinsics.c \ unwind.h unwind.c mini-posix.c \ mini-arm.c exceptions-arm.c tramp-arm.c image-writer.c \ dwarfwriter.c mini-gc.c LOCAL_PRELINK_MODULE := false LOCAL_CFLAGS := $(MONO_CFLAGS) -fPIC LOCAL_C_INCLUDES := $(MONO_INCLUDES) LOCAL_WHOLE_STATIC_LIBRARIES := monoutils gcarm monoruntime LOCAL_STATIC_LIBRARIES := wapiarm monoruntimearm eglib gc wapi mini miniarm LOCAL_LDFLAGS := -Wall -L$(SYSROOT)/usr/lib -llog -ldl -lm -lc #LOCAL_STRIP_MODULE := false include $(BUILD_SHARED_LIBRARY) # build 'mono' include $(CLEAR_VARS) LOCAL_ARM_MODE := arm LOCAL_MODULE := mono LOCAL_MODULE_TAGS := eng LOCAL_PATH := $(MONO_PATH)/mono/mini LOCAL_SRC_FILES := main.c LOCAL_CFLAGS := $(MONO_CFLAGS) LOCAL_C_INCLUDES := $(MONO_INCLUDES) LOCAL_SHARED_LIBRARIES := libmono LOCAL_LDFLAGS := -llog -ldl -lm -lc include $(BUILD_EXECUTABLE)
長いですね・・・。あとでgithubかなんかに突っ込んで終わりにしたいですね。
Application.mkは適当に
APP_ABI := armeabi armeabi-v7a
とか書いておけば良いです。
あてるパッチはこんな感じです。
diff --git a/libgc/dyn_load.c b/libgc/dyn_load.c index e4be3c7..d8ce7ec 100644 --- a/libgc/dyn_load.c +++ b/libgc/dyn_load.c @@ -99,7 +99,9 @@ # if !defined(OPENBSD) # include <elf.h> # endif +# if defined(HAVE_LINK_H) # include <link.h> +# endif #endif /* Newer versions of GNU/Linux define this macro. We diff --git a/mono/mini/aot-runtime.c b/mono/mini/aot-runtime.c index a3c5746..867e437 100644 --- a/mono/mini/aot-runtime.c +++ b/mono/mini/aot-runtime.c @@ -38,8 +38,12 @@ #endif #ifdef HAVE_DL_ITERATE_PHDR +#ifdef PLATFORM_ANDROID +#include <linker.h> +#else #include <link.h> #endif +#endif #include <mono/metadata/tabledefs.h> #include <mono/metadata/class.h> @@ -59,6 +63,21 @@ #include "mono/utils/mono-compiler.h" #include <mono/utils/mono-counters.h> +#if defined(PLATFORM_ANDROID) +#ifdef PSR_c +#undef PSR_c +#endif +#ifdef PSR_x +#undef PSR_x +#endif +#ifdef PSR_s +#undef PSR_s +#endif +#ifdef PSR_f +#undef PSR_f +#endif +#endif + #include "mini.h" #include "version.h" diff --git a/mono/mini/mini-posix.c b/mono/mini/mini-posix.c index c15b098..92aa901 100644 --- a/mono/mini/mini-posix.c +++ b/mono/mini/mini-posix.c @@ -631,7 +631,7 @@ mono_runtime_syscall_fork () return (pid_t) syscall (SYS_fork); #else g_assert_not_reached (); - return; + return -1; #endif }
これもあとでどっかにファイルおくだけにしたいですね・・・。
さて残りはヘッダなんですが、ソースをそのまま貼り付けるとえらいことになるので、
あとでgithubにでも突っ込んでおきます。
突っ込んだらこの記事も更新するつもりです。
libusbをAndroid用にポーティングする
お仕事で必要があってlibusbをAndroidに持っていくということをやりました。
この記事はlibusbをAndroid用にbuildする方法の備忘録です。
まず、Androidをlibusbにportingするのは先人が既にやっているので、そこを参考にします。
参考URL: http://android.serverbox.ch/?p=151
- androidのソースコードをもってきます。 -> ここ「Downloading the Source Tree | Android Open Source」を参考に。
- androidのソースコードをbuildします。
- externalの下にlibusbというディレクトリを切ります。
- libusbのソースを展開します。現在の最新版は「libusb-1.0.9」です。
- "external/libusb"の直下に「Android.mk」を作成します。
- "external/libusb/libusb"にも「Android.mk」を作成します。
- "external/libusb/libusb/io.c"を修正します。
- 「mm」でlibusbをbuildします。
androidのbuildは、もってきたsource codeのトップで
$ source build/envsetup.sh
$ lunch
$ make
とかやってください。
libusbの直下に作成するAndroid.mkはこんな感じです。
LOCAL_PATH := $(call my-dir) subdirs := $(addprefix $(LOCAL_PATH)/,$(addsuffix /Android.mk, libusb)) include $(subdirs)
元にしているページのAndroid.mkは"subdirs"の頭の"s"が取れてしまっているので注意しましょう。
"external/libusb/libusb"の下に作成するAndroid.mkはこんな感じです。
LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_CFLAGS:=-DLIBUSB_DESCRIBE LOCAL_SRC_FILES:= \ core.c \ descriptor.c \ io.c \ sync.c \ os/linux_usbfs.c \ os/threads_posix.c LOCAL_C_INCLUDES += \ external/libusb/ \ external/libusb/libusb/ \ external/libusb/libusb/os LOCAL_MODULE:= libusb LOCAL_MODULE_TAGS:=eng LOCAL_PRELINK_MODULE:=false include $(BUILD_SHARED_LIBRARY)
"libusb-1.0.9"以外のバージョンでは何らかの修正が必要になるかもしれません。
その場合は適宜修正して下さい。
あと、この方法でビルドはできると思いますが、ビルド後のバイナリの動作を保証するものではありません。
NSEG勉強会 feat. 高専カンファレンスの感想
2012年6月23日に長野で行われた「NSEG勉強会 feat. 高専カンファレンス」についての記事です。
勉強会の開催情報は↓のページに載っています。
NSEG勉強会 feat. 高専カンファレンス - 高専カンファレンス Wiki
前回の日記に書きましたが、今回の勉強会には発表者として参加してきました。
これまでにも長野へ行くチャンスはあったのですが、体調不良で過去のチャンスを逃したため、今回が初めての長野となりました。
長野って近いようで遠いなーと思いました。
長野に着くなりお約束のお蕎麦を食べたのですが、写真撮りそこねてしまいました。
ちゃんと写真撮っとけばよかったなー。
信州そば美味しかったです。
今回の発表は実はiPadを使ってやろうかなーと思い、iPadからVGA出力をするアダプタも購入したのですが、
なぜかきちんと出力されず、結局諦めてノートPCを使ってプレゼンしました。
ちょっと悲しかったです(´;ω;`)
信州大学の教官の方の発表は、畑違いではあったものの話が面白くすごくわかり易く感じました。
実際の教育機関で教鞭をとられている人はさすがだなーと思いました。
今回の勉強会はばりばりのソフトウェア畑の勉強会ということで、
開発よりのお話が多かったかなーと思います。
その割にガチガチの技術ネタばかりではなかったので、
わりととっつきやすい感じの勉強会だったかなという印象を持ちました。
あと、長野周辺の方が半数を占めるのもあってか、
NSEGというのはかなりアットホームな感じの勉強会なのだなーと感じました。
長野にいるソフトウェア技術者の方は顔を出してみれば、きっと優しく迎え入れてくれると思いますよ。
今回発表の場を提供して頂いたNSEG感じのおびなたさん、
勉強会運営スタッフのみなさん、
私の話を聞いて頂いた参加者の皆さん、
どうもありがとうございました。
「NSEG勉強会 feat. 高専カンファレンス」に参加してます。
まだ終わってないので感想は後ほど。
長野で行われている「NSEG勉強会 feat. 高専カンファレンス」に参加しています。
私も15分の枠を頂いて発表をしてきました。
タイトルは「Hello, Ruby!」で、mrubyの紹介と私の作っているjamrubyの紹介の話をしてきました。
発表資料はこちらです。
DropBoxのリンク : https://www.dropbox.com/s/ajb5pp9qtt13aeb/HelloRuby.pdf
発表の様子は録画されているそうなので、Ustreamで見られなかった方も後ほど公開される予定の録画をご覧頂くことができるそうです。
AndroidのPreferenceを簡単に使いたい
AndroidでPreference関係の処理書くのすごーく面倒なんですよねー。
もう面倒すぎて鼻血でそうな感じですよね。
なので、うまいこと使える部品使って使い回したいなーっと。
そういうことで最近はこんな感じのコード書いてます。
public class Preferences { private static SharedPreferences prefs; private static Resources res; public static void create(Context context) { if (null == prefs || null == res) { prefs = PreferenceManager.getDefaultSharedPreferences(context); res = context.getResources(); } } public static String getHoge() { return get(R.string.pref_key_hoge, getString(R.string.pref_defval_hoge)); } private static String getString(int id) { return res.getString(id); } @SuppressWarnings("unchecked") private static <T> T get(int id, T defVal) { final Map<String, ?> map = prefs.getAll(); final String key = getString(id); if (!map.containsKey(key)) { return defVal; } return (T)map.get(key); } }
Preferences#createをActivityのonCreateとかonStartとかonResumeとかで適宜呼び出します。
(AndroidのSingletonはアプリケーションのlife cycleにあわせて自動的にunloadされる可能性があるので気をつけてくださいね☆)
内部で設定項目を取得するのは"
デフォルト値やキーは基本的にリソースに追い出して使う前提なので、
"String getString(int id)"でリソースから文字列を取得できるようにしています。
こんな感じのラッパーを書いておけば設定項目へのアクセスが楽になるかなーと思います。
jamrubyのリポジトリを分離しました。
Androidのセンサーで気をつけるべきこと
「気をつけるべきこと」とか書きましたが、
ありていに言えば「自分がはまったのでくやしい!ぐぬぬ!」ってことですね。
ということでAndroidのセンサーから値を取得する上で、気をつけなきゃいけないこと書いておきます。
- SensorManager取得時に指定したセンサーのタイプを信用するな。
- SensorのResolutionはよくわからない。
具体的にどういうことかコードを見ていきましょう。
Androidでセンサーの値を取るときはこんな感じのコードを書きます。
@Override void onCreate(Bundle savedInstanceState) { ... final SensorManager mgr = (SensorManager)getSystemService(SENSOR_SERVICE); final Sensor acc = mgr.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); mgr.registerListener(listener, acc, SensorManager.SENSOR_DELAY_NORMAL); } private final SensorEventListener listener = new SensorEventListener() { @Override public void onSensorChanged(SensorEvent event) { ... } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { } };
このとき、SensorManagerに対して指定したセンサータイプのセンサのイベントが取れるようになります。
きっと取れると思います。取れるはずなんです。本当なら。
でも実はうまくいかないことがよくあります。
で、よくよく調べてみると、Android端末のいくつかでは指定したセンサータイプと、
getDefaultSensorで実際に取得できるセンサーの物理的な種類が一致していないことがわかりました。
そりゃうまく動かないわけですよ。
だって加速度センサの値が欲しいのに実際には磁気センサを取得してたりするんですから。
これをどうやって回避するかというと、実際に取得したいセンサに関連する他の論理センサも動作させるということを行います。
具体的なコードで説明をすると、
final Sensor acc = mgr.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); mgr.registerListener(listener, acc, SensorManager.SENSOR_DELAY_NORMAL); final Sensor ori = mgr.getDefaultSensor(Sensor.TYPE_ORIENTATION); mgr.registerListener(listener, ori, SensorManager.SENSOR_DELAY_NORMAL); final Sensor mag = mgr.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD); mgr.registerListener(listener, mag, SensorManager.SENSOR_DELAY_NORMAL);
こんなふうにして関連するセンサを全部使用します。
後はイベントを受ける側で、どのイベントが来たかを振り分けてあげればうまくいきます。
(どうして加速度センサと磁気センサと傾きセンサが関連するかの説明は省略します)
private final SensorEventListener listener = new SensorEventListener() { @Override public void onSensorChanged(SensorEvent event) { switch(event.sensor.getType()) { case Sensor.TYPE_ACCELEROMETER: ... break; } } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { } };
次にSensorのResolutionですが、名前からして測定値を物理量に変換するのに使用するものだと思うじゃないですか普通は(たぶん普通の感覚だよね?)。
でもこれ、実は実装によってはただの固定値であまり意味のある値が入っていません。
Resolutionを使わなくても、普通に値を使えば物理量に単位変換された値が入っています。
Resolutionの単位も実装依存のため、何のために存在するかいまいちわかりません。
なので間違っても↓みたいなコードは書いちゃだめですよ!ダメ、ゼッタイ!
private final SensorEventListener listener = new SensorEventListener() { @Override public void onSensorChanged(SensorEvent event) { final float res = event.sensor.getResolution(); switch(event.sensor.getType()) { case Sensor.TYPE_ACCELEROMETER: final float accX = event.value[0] * res; // do something ... break; } } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { } };
↑こういうことしちゃダメですよ!