Rubyでlibmecab.dllを本当に呼び出してみる

RubyからMeCabを呼び出したかったんだけど,Windows環境だとbindingがうまく動かないらしい.なので,直接dllをexternして関数を呼び出したりしているらしい.こちらの方が実装を公開しているようです.

http://nlp.sfc.keio.ac.jp/~aihara/nlp.html

ここにあがっているmecab.rbなんですが,mecab_sparse_tonodeは使わないでstrのほうの結果をパースしているようです.なので,mecab_sparse_tonodeのほうを使えるように改造してみました.

dl/import#structは,内部に構造体を持てないらしいので,void*にしてひたすらWrapperを書きました.ソースコードをGistにあげときます.

https://gist.github.com/2927253

 

もとのソースコードMeCab 0.94を対象にしてますが,こっちは最新のMeCab 0.994を対象にしています.mecab_sparse_tonodeの仕様が違うようなので,注意.

PreferenceActivityで動的にsummaryを設定する 自分なりの方法で

Androidの設定画面は,PreferenceActivityを使うと便利ですよね.
SharedPreferenceに値を勝手に保存してくれます.

 PreferenceのUIは下の画像のように,タイトルとサマリーがあります.

f:id:nanofi:20120217134617p:plain

ここの,サマリーに設定の値が表示されるといいなってことで,「PreferenceActivity 動的」とかしらべると色々やり方が見つかります.
今回は,それらの色々を統合して自分なりに実装してみました.

// setting.xml<?xmlversion="1.0"encoding="utf-8"?>
<PreferenceScreenxmlns:android="http://schemas.android.com/apk/res/android">
<ListPreference
android:entries="@array/entries"
android:entryValues="@array/entry_values"
android:key="list"
android:title="@string/title"
</PreferenceScreen>

// SettingActivity.java
public
class SettingActivity extends PreferenceActivity implements OnSharedPreferenceChangeListener{
  @Override
  protected void onCreate(final Bundle savedInstanceState){
    super.onCreate(savedInstanceState);
    this.addPreferencesFromResource(R.xml.setting);
  }

  public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key){
     final Preference preference = getPreferenceScreen().findPreference(key);
     if(preference instanceof ListPreference){
       final ListPreference listPreference = (ListPreference)preference;
       final CharSequence entry = listPreference.getEntry();
       listPreference.setSummary(entry == null ? "" : entry);
     }
  }
  @Override
  protected void onResume(){
    super.onResume();
    final ListPreference list = (ListPreference)getPreferenceScreen().findPreference("list");
    final CharSequence entry = list.getEntry();
    pathOrder.setSummary(entry == null ? "" : entry);
    getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
  }
  @Override
protected void onPause(){
     super.onPause();
     getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
  }

主要な部分は,OnSharedPreferenceChangeListener.onSharedPreferenceChangedメソッド内のコードですね.変更されたPreferenceがListPreferenceだった時summaryをEntryに更新しています.
さらに,リスナーをonResumeで登録,onPauseで解除しています.このとき,初期値を設定していますが,ほかにいい方法が有りそうな予感.onCreateでリスナーを登録すると設定されるのかな?

instanceofは速度面が心配だったりしますが.これですべてのListPreferenceが更新された瞬間を対応できます.

 

おすすめのGUIなGit/Mercurialツール for Mac

皆さん,バージョン管理ツール使ってますよね.SubversionとかGitとかMercurialとか.自分は,よくGit使ってソースコードなどのバージョン管理をしてます.
最近AppStoreを見ていたら,分散型バージョン管理システムGit/Mercurial向けのよさげなGUIツールを見つけたので,紹介したいと思います.
SourceTree: http://www.sourcetreeapp.com/

ツールを起動すると,管理しているリポジトリ一覧が表示されます.リポジトリは,クローンしたフォルダをウィンドウにドロップするか,リポジトリの追加から管理に追加することができます.Gitでしか使ってみていませんが,コミット,プッシュ,プルやブランチ,タグの作成など基本的な機能は揃っていて,ログがグラフ構造で見れるので気に入っています.
みなさんもぜひ.

カレンダーのイベント取得できたかな?

この記事の続きですが,カレンダーのデータを取得できたので報告したいと思います.

Androidandroid.provider.Calendarのソースコードを参考にすると,大体取得する方法がわかると思います.そのソースではContentProvider経由でデータを取得していたので,ContentProviderから標準のカレンダーのデータを取得する方法を紹介したいと思います.

基本的には,Android公式ドキュメントのContentProviderの説明を把握しといたほうがいいと思います.
http://developer.android.com/intl/ja/guide/topics/providers/content-providers.html
ドキュメントにあるように,データにアクセスするためのURIを記述し,それを実行することでデータを取得したり更新したりするようです.

では,例としてカレンダーの現在の時刻から1日分のイベントのタイトルを取得してみたいと思います.ソースとしては,android.provider.Calendar.Instancesクラスにかいてある内容です.

ContentResolver resolver = getContentResolver();
Uri uri = new Uri("content://com.android.calendar/instances/when");
// アンドロイドのバージョンコードが7以下の時(Android2.1以下)は,com.android.calendarの代わりにcalendarにして下さい.
Uri.Builder builder = uri.buildUpon();
ContentUris.appendId(builder, System.currentTimeMillis());
ContentUris.appendId(builder, System.currentTimeMillis() + 24 * 60 * 60 * 1000);
Cursor cursor = resolver.query(builder.build(), new String[]{}, "selected = 1", null, "begin ASC");
int titleIndex = cursor.getColumnIndex("title");
while(cursor.moveToNext()){
  Log.d("INFO", "Title: " + cursor.getString(titleIndex));
}

こんな感じですね.これで,ログにタイトルが一覧されます.Instanceは,繰り返すイベントとかを含めて実際の時間で検索したい時とかに使うみたいです.まあ,繰り返しイベントを含めてある範囲のイベントを取得したいときは,Instanceを使うといいみたいですね.このコードでbuilder.build()の出力URIが"com.android.calendar/instances/when/現在時刻のunixtime/1日後のunixtime"となっていました.

その他のURIとかは,ソースを参考にするといいと思います.ソースのとってきかたは,google:Android ソースコードとかで検索するとだいたい分かると思います.カレンダー取得のソースの場所は,
/frameworks/base/core/java/android/provider/Calendar.java
です.

カレンダーのイベント取得に関するメモ

Androidの標準のカレンダー機能から,イベントデータを取得したい.API14から,CalendarContractとかのが追加されているけど,Android2.1から対応させたいし,それだと取得できるのかな?と思って調べてました.

なにやら,Content Providerとかうのを使うと取得できるようですね.使う方法が,Android2.1,Android2.2の間で変わっているようです.
http://d.hatena.ne.jp/rmiya/20100725/1280028729

なるほど.なるほど.標準の実装もオープンソースだから見れるんですね.ちょっとどうなってるのか見てきたいと思います.repoいれて,ソース落としてみます.

今日は時間なかったので,簡単にこんな感じで.