« 2008年08月 | メイン | 2008年10月 »

2008年09月 アーカイブ

2008年09月02日

SensorSimulator - OpenIntents

2009.02.14 追記:この記事の内容は若干古くなっています。こちらの投稿も併せてご覧下さい。


OpenIntentsという、Google Codeのプロジェクトがあります。このプロジェクトでは、役に立つライブラリやアプリ、ツールがいくつか公開されています。8/29頃に概ねver.0.9 betaに対応されているようです。OpenIntentsには、SensorSimulatorというツールが含まれています。このツールは、加速度やコンパス、回転(傾き)のセンサー入力部を、ソフトウェアでシミュレートするものです。SensorSimulatorがサーバーとなり、アプリからソケットで接続する構成です。SensorSimulatorは、デバイスの回転運動の表現にロール・ピッチ・ヨー(roll, pitch, yaw)角を用いています。簡単な解釈は以下の図をご覧下さい。(下図は端末を地面に水平に置いた時の想定です。)

rollpitchyaw

SensorSimulatorを使うと、この動画のようにセンサーからの入力を受け付ける(SensorListenerをインプリしている)アプリを操作することができます。


使い方に関する簡単な説明を書きます。

・はじめに

  • Java 6じゃないとダメです

  • OpenIntentsはeclipseで開発されているので、eclipseを使った方が楽です

  • 現時点でリリースされているOpenIntents 0.1.7は、SDK 0.9 betaに対応していないので、SVNからチェックアウトする必要があります。私は、rev.1065で動作確認しました。

・セットアップ

 まず、SensorSimulator(http://openintents.googlecode.com/svn/trunk/tools/SensorSimulator)をチェックアウトし、org.openintents.tools.sensorsimulator.SensorSimulatorを実行します。Simulatorのウィンドウが表示されるはずです。この時点でエミュレータからの接続を待っている状態になっています。

simulator

 次に、OpenIntentsのコア部をエミュレータにデプロイする必要があります。しかし、現時点でリリースされている0.1.7は、SDK 0.9 betaに対応していないので、SVN(http://openintents.googlecode.com/svn/trunk/openintents)からチェックアウトし、エミュレータにデプロイして下さい。(eclipseの場合、OpenIntentsプロジェクトをAndroid Applicationとして起動)

 OpenIntentsが起動したら、“setting”タブを開き“Sensor Simulator”を押します。

setting

 ここでエミュレータからSensorSimulatorが待ち受けているIPアドレスやポート番号を設定します。

setting2

これで準備は完了です。OpenIntentsのOpenGLのサンプル(http://openintents.googlecode.com/svn/trunk/samples/OpenGLSensors)で動作を確認してみて下さい。

・使用上の注意

SensorSimulatorを使う上で、いくつか気にしておいた方がよいポイントや注意点があります。

  • openintentsのjarを含まねばなりません。(OpenGLSensorsに含まれるopenintents-lib.jarを使えばよいと思います。)
  • アプリ側のコードがOpenIntentsに依存することになります。 まず、初期化時(onCreateなど)に以下のおまじないコードが必要です。

    OpenIntents.requiresOpenIntents(this);
    Hardware.mContentResolver = getContentResolver();

    SensorManagerのインスタンスは、SensorManagerSimulatorでなければなりません。

    SensorManager sensorManager = (SensorManager) new SensorManagerSimulator((SensorManager) getSystemService(SENSOR_SERVICE));

    アプリがアクティブになる際(onResumeなど)に、ソケットを開くstaticメソッドをコールする必要があります。

    SensorManagerSimulator.connectSimulator();

    アプリが非アクティブになる際(onStopなど)に、ソケットを閉じるstaticメソッドをコールする必要があります。

    SensorManagerSimulator.disconnectSimulator();



安直に書くとこんな感じです。

public class SensorExample extends Activity implements SensorListener {
 SensorManager sensorManager;
 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  // --- views
    ・・・
  // --- sensors
  OpenIntents.requiresOpenIntents(this);
  Hardware.mContentResolver = getContentResolver();
  sensorManager = (SensorManager) new SensorManagerSimulator((SensorManager) getSystemService(SENSOR_SERVICE));
 }
 @Override
 protected void onStop() {
  sensorManager.unregisterListener(this);
  SensorManagerSimulator.disconnectSimulator();
  super.onStop();
 }
 @Override
 protected void onResume() {
  super.onResume();
  SensorManagerSimulator.connectSimulator();
  sensorManager.registerListener(this,
  SensorManager.SENSOR_ACCELEROMETER |
  SensorManager.SENSOR_MAGNETIC_FIELD |
  SensorManager.SENSOR_ORIENTATION,
  SensorManager.SENSOR_DELAY_FASTEST);
 }
 public void onSensorChanged(int sensor, float[] values) {
  ・・・
 }
}

ハードに疎く、エミュレータだけが頼りの開発者(私のような..汗)がテストする用途には充分使えるような気がします。

2008年09月03日

Google Chrome

WebKitは開発ツールもMacがメインのターゲットと言う感じで、Windowsだと色々と結構めんどくさそうですが、Chromeが賑やかになると、Winユーザーも色々と楽しいことがありそうですね。
そして、ChromeはWebKitを使っているということで、Androidとのコラボが非常に楽しみになります。色々と可能性が開きそうです。

gmailがかなり快適に使えますね。私は、仕事用も個人用もどちらもgmailなので、アクセスが速くなるのはかなり嬉しいです。
全体的にSafariより高速な気がするのはなぜでしょう。私のMacがただ遅いだけかもしれませんが。

2008年09月05日

加速度計 - Android

2009.02.14 追記:この記事の内容は若干古くなっています。こちらの投稿も併せてご覧下さい。


先日ポストした、Android関連プロジェクトのOpenIntentsのSensorSimulatorを使って遊ぶ目的で簡単なサンプルを作ってみました。

加速度センサーを使っています。上下左右(端末の側面方向)にある程度以上強く動かすと、動かした速度に応じてその方向へ地図が移動します(一応orientation sensorも見て端末の傾きを考慮していますので、どのような持ち方をしていても大丈夫な、、、はずです)。また、正面方向に動かすと、ズームイン、正面と反対(背中)方向に動かすとズームアウトします。

加速度を知るには、android.hardware.SensorListenerインタフェースのメソッド

void onSensorChanged(int sensor, float[] values)


の第1パラメータ(int sensor)が、SensorManager.SENSOR_ACCELEROMETERであるときの、第2パラメータの値(float[] values)を拾う必要があります。この値は要素数3(公式ドキュメントでは、それぞれX, Y, Zと呼んでいます)のfloatの配列(float[] values)です。各要素の値の意味ですが、加速度センサーの場合は

  • X(1つ目の要素)は、端末の右面からの加速度合(右面と垂直な方向のベクトル)

  • Y(2つ目の要素)は、上部からの加速度合

  • Z(3つ目の要素)は、前面(正面)からの加速度合


となります。(下図な感じの雰囲気。)

accerelometer1

ベクトルの度合は、重力加速度(9.82m/s^2)を基準とするようです。加速度計は重力の影響を受けます。地球ならその面を真下に向けると1、真上に向けると-1を示します。例えば、端末の正面が上に来るように地面に置いた状態では、XとYは約0、Zは約-1となります。(下図な感じの雰囲気。)

accerelometer2

加速度計が受ける重力の影響は、端末の傾き(端末をどう持っているか)によって逐次変化しますので、端末の傾きによって挙動に差が出ないアプリを作ろうとした場合は、傾きを考慮した調整が必要です。

 次に、端末と向かい合っている状態(X:0, Y:-1, Z:0)で、端末を左右に動かした場合を考えます。端末を右へ移動させるとXは増え、左に移動させた場合はXは減ります。ただし、これは非常にゆっくり移動させた場合の話で、ある程度以上の勢いをつけた(振るなど)場合は、慣性力の影響で、一旦逆向きの力が働くことに注意する必要があります。(勢いよく車を加速させて発進すると、後ろに引っ張られるのと同じです。)

サンプルのソースは「ここ」に置いています。eclipseプロジェクトを固めたものです。OpenIntentsに依存しているので、動かすためにはOpenIntentsとSimulatorの設定が必要です。詳しくは先日のエントリ(こちら)を参照して下さい。

ご覧になった方、もしバグッてたら、教えて頂けると嬉しいです。

2008年09月08日

日本Androidの会

「日本Androidの会」という団体が9/12(金)に設立されます。
富士ソフト秋葉原ビル(http://www.fsi.co.jp/company/akihabara.html)で9月12日19時から発足式典があります。無料ですし、Googleの人も講演されるとのことですので、皆さん申し込みましょう。

申し込みページ:https://www.c-sq.com/modules/eguide/event.php?eid=48

「日本Androidの会」は、Androidに興味をもつ全てのユーザが参加可能なコミュニティです。
詳細:
http://www.android-group.jp/index.php?%B9%D6%B1%E9%2F%C8%AF%C2%AD%BC%B0%C5%B5


2008年09月16日

Hibernate - 固定長文字列(CHARなど)のカラムに対して半角スペースでpaddingしたい

自分ではカラムの型に固定長文字列を使った事がなかったので、このような問題に遭遇したことがありませんでした。解決方法の例としては、アプリケーションのコードで毎回やる方法もありますが、ユーザー型(UserType)を使う方法とかもあります。ユーザー型の場合は、以下のような感じのクラスを作ります。

package example.usertype;

public class RightPadUserType implements UserType, ParameterizedType {
  public int[] sqlTypes() {
    return new int[] { Types.VARCHAR };
  }
  public Class returnedClass() {
    return String.class;
  }
  public boolean equals(Object x, Object y) throws HibernateException {
    return EqualsHelper.equals(x, y);
  }
  public int hashCode(Object x) throws HibernateException {
    return x.hashCode();
  }
  public Object assemble(Serializable cached, Object owner)
      throws HibernateException {
    return cached;
  }
  ・・・(省略)
  public Object nullSafeGet(ResultSet rs, String[] names, Object owner)
      throws HibernateException, SQLException {
    String value = rs.getString(names[0]);
    if(value==null)
      return "";
    return value;
  }
  
  public void nullSafeSet(PreparedStatement st, Object value, int index)
      throws HibernateException, SQLException {
    if (value == null) {
      st.setNull(index, Types.NULL);
    } else {
      st.setString(index, StringUtils.rightPad((String)value, length));
    }
  }
  // カラム長
  private int length = 0;
  public void setParameterValues(Properties properties) {
    if(properties.get("length") != null)
      length = Integer.parseInt((String)properties.get("length"));
  }
}

trimしてもいいのですが、trimだと検索時にindexが効かず遅くなりそうなので、padする方がよいような気がします。ただ、そうすると、カラム長を教えてあげる必要があります(※1)。以下はhbmで書いた場合の例です。

<hibernate-mapping>
 <class name="example.Job" table="Jobs">
・・・
    <property name="name">
      <type name="example.usertype.RightPadUserType">
       <param name="length">10</param> ※1
      </type>
    </property>
・・・
  </class>
</hibernate-mapping>

自動生成する方法を作って工夫しないと面倒そうです。あまりいい方法ではないかもしれません。


2008年09月26日

Android - VIEW_ACTIONのIntentでStreet Viewを開く

Android SDK の0.9から、公式なIntentの種類にStreetViewが追加されています。(http://code.google.com/android/reference/available-intents.html
なので、IntentでStreetViewを開くことが可能です。

エミュレータを起動しておき、ターミナルからadbで実験してみます。

adb shell
# am start -a android.intent.action.VIEW 'google.streetview:cbll=35.713768,139.777254&cbp=1,0,,0,1.0'

この座標は上野駅周辺ですので、上野駅付近のStreetViewが開いたと思います。cbllパラメータは、緯度経度情報です(必須)。cbpはヨーとピッチ等の角度を指定します。ロールは見ていないようです。他にも、Mapに表示を切り替えた時のズームレベルなども指定可能です。

アプリから実行する例はこんな感じです(ちょっとダサいですが。。)以下は、MapViewに表示されている中央の座標のStreetViewを表示します。

GeoPoint center = map.getMapCenter();
Uri uri = Uri.parse("google.streetview:cbll=" + center.getLatitudeE6()/1E6 + "," + center.getLongitudeE6()/1E6);
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);

なお、このIntentのactionはVIEWになるので、startActivityForResultなどで、サブアクティビティとして起動し、戻り値をもらうような使い方は出来ません。(一方通行のやり取りになってしまうようです。)また毎回StreetViewアプリが起動するので、端末からStreetViewアプリを直接操作する時のような軽快な操作は期待できません。でも、いずれ出来るようになるような気がします。

ちなみに、地図に表示している地域がStreetViewに対応しているかどうかを示す青線(WEBのGoogle Mapで「ストリートビュー」ボタンを押した時に出るアレ)は、MapView#setStreetView(true)とすれば表示されます。

About 2008年09月

2008年09月にブログ「GrandNature」に投稿されたすべてのエントリーです。過去のものから新しいものへ順番に並んでいます。

前のアーカイブは2008年08月です。

次のアーカイブは2008年10月です。

他にも多くのエントリーがあります。メインページアーカイブページも見てください。