(2011-02の一覧)
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
2011-02-24 Thu (他の年の同じ日: 2005 2006)
SQLiteのデータベースファイルをSDカードに保存
2011-02-24-1 / カテゴリ: [SQL][Android] / [permlink]
というのを年末調べてたけどまだまとめてなかったので。
内蔵ストレージに作られたファイルをコピーじゃなくて、最初からSD保存する構成。
大容量のデータを扱いたいとかデバッグ時とか。
というか、書籍やネットで「ファイル名を指定」している箇所をフルパスで指定(してandroid.permission.WRITE_EXTERNAL_STORAGEを付加)すればOK
SDK付属サンプルのNotePadであれば、
あとはファイルの暗号化機能とかあればなぁ…
内蔵ストレージに作られたファイルをコピーじゃなくて、最初からSD保存する構成。
大容量のデータを扱いたいとかデバッグ時とか。
というか、書籍やネットで「ファイル名を指定」している箇所をフルパスで指定(してandroid.permission.WRITE_EXTERNAL_STORAGEを付加)すればOK
SDK付属サンプルのNotePadであれば、
--- src/com/example/android/notepad/NotePadProvider.java.org 2011-01-20 16:43:58.312750000 +0900 +++ src/com/example/android/notepad/NotePadProvider.java 2011-02-24 21:06:29.551900000 +0900 @@ -30,6 +30,7 @@ import android.database.sqlite.SQLiteOpenHelper; import android.database.sqlite.SQLiteQueryBuilder; import android.net.Uri; +import android.os.Environment; import android.text.TextUtils; import android.util.Log; @@ -43,7 +44,7 @@ private static final String TAG = "NotePadProvider"; - private static final String DATABASE_NAME = "note_pad.db"; + private static final String DATABASE_NAME = Environment.getExternalStorageDirectory() + "/note_pad.db"; private static final int DATABASE_VERSION = 2; private static final String NOTES_TABLE_NAME = "notes";するとこんな感じ。(DesireIIで確認)
% adb shell ls -l /mnt/sdcard/note_pad.db ----rwxr-x system sdcard_rw 4096 2011-02-24 11:50 note_pad.db
あとはファイルの暗号化機能とかあればなぁ…
2011-02-22 Tue (他の年の同じ日: 2007 2008)
nkfでエンコード変更して上書き保存
2011-02-22-2 / カテゴリ: [win][cygwin] / [permlink]
--overwrite または --in-place する。
--overwrite はタイムスタンプを変更しない。
--in-place はタイムスタンプが更新される。
-w は utf-8 へ変更
% find . -name "*.java" | xargs nkf -w --overwriteデフォルトだと標準出力へエンコード変更結果を出力するけど、find|xargsと組み合わせて複数ファイル一気に変更、なとき。
--overwrite はタイムスタンプを変更しない。
--in-place はタイムスタンプが更新される。
-w は utf-8 へ変更
ソースからnkfインストール
2011-02-22-1 / カテゴリ: [win][cygwin] / [permlink]
[2005-12-21-3]の日記だと、http://cygwin-je.sourceforge.jp/cygwin_je/ からパッケージインストールしてたみたいだけど、今試したら setup.bz2.sig がないなどエラーになってインストールできなかったので結局makeした。
ソースは http://sourceforge.jp/projects/nkf/ から。
今日の時点で ver 2.1.1 (2010-09-13版)
wget すると、すでにMakefileはあるので
インストール先を変えたければ Makefile の prefix をイジればいいはず(未確認)
ソースは http://sourceforge.jp/projects/nkf/ から。
今日の時点で ver 2.1.1 (2010-09-13版)
wget すると、すでにMakefileはあるので
% make % make test % make installで /usr/local 以下にインストールされる。
インストール先を変えたければ Makefile の prefix をイジればいいはず(未確認)
2011-02-17 Thu (他の年の同じ日: 2005 2006)
ボリューム変更ハードキーのハンドリング
2011-02-17-2 / カテゴリ: [Android] / [permlink]
動作確認用アプリなんかで手抜きをしたい^a^k上下スクロールとかズームイン/アウトなんかにキー操作を割り当てしたい場合に。
標準だと「押す:ボリューム変更&UI表示 / 離す:通知音を鳴らす」という動作のため、KEYCODE_VOLUME_UPとKEYCODE_VOLUME_DOWNの両方をフックする必要がある。
というわけで、こんな感じ。
Androidでキー長押しはACTION_DOWNがコールバックされまくるんだな。
参考
キーイベントに応答するには - 逆引きAndroid入門
ハードキーフックの方法 - 明日の鍵
標準だと「押す:ボリューム変更&UI表示 / 離す:通知音を鳴らす」という動作のため、KEYCODE_VOLUME_UPとKEYCODE_VOLUME_DOWNの両方をフックする必要がある。
というわけで、こんな感じ。
@Override public boolean dispatchKeyEvent(KeyEvent event) { switch (event.getAction()) { case KeyEvent.ACTION_DOWN: switch (event.getKeyCode()) { case KeyEvent.KEYCODE_VOLUME_UP: // ここにボリュームupが押されたときに走らせたい処理 return true; case KeyEvent.KEYCODE_VOLUME_DOWN: // ここにボリュームdownが押されたときに走らせたい処理 return true; default: break; } break; case KeyEvent.ACTION_UP: switch (event.getKeyCode()) { case KeyEvent.KEYCODE_VOLUME_UP: case KeyEvent.KEYCODE_VOLUME_DOWN: // キーが離された場合はイベントを捨てる return true; default: break; } break; default: break; } return super.dispatchKeyEvent(event); }
Androidでキー長押しはACTION_DOWNがコールバックされまくるんだな。
参考
キーイベントに応答するには - 逆引きAndroid入門
ハードキーフックの方法 - 明日の鍵
find|xargsでスペース込みのパスが有る場合
2011-02-17-1 / カテゴリ: [linux][command] / [permlink]
$ find path [opt] -print0 | xargs -0 commandでGo
これで、findの結果が\0区切りになり、xargsのデリミタの扱いが\0になる。
http://linuxjm.sourceforge.jp/html/GNU_findutils/man1/xargs.1.html
例: "a b.txt" がある場合
zaki@salva% find . -name "*txt" [~/tmp/path] ./a b.txt ./a.txt ./b.txt ./sub/a b.txt ./sub/a.txt ./sub/b.txtこんなディレクトリ構成の場合("a b.txt"がある)
zaki@salva% find . -name "*txt" | xargs file [~/tmp/path] ./a: ERROR: cannot open `./a' (No such file or directory) b.txt: empty ./a.txt: empty ./b.txt: empty ./sub/a: ERROR: cannot open `./sub/a' (No such file or directory) b.txt: empty ./sub/a.txt: empty ./sub/b.txt: empty"a"とか"b.txt"なんかねーよといわれる。
これは、findの結果が改行区切りで出力されるためで、更にxargsが改行とスペースを区切りとみなしているため。
zaki@salva% find . -name "*txt" | od -c [~/tmp/path] 0000000 . / a b . t x t \n . / a . t x 0000020 t \n . / b . t x t \n . / s u b / 0000040 a b . t x t \n . / s u b / a . 0000060 t x t \n . / s u b / b . t x t \n 0000100んで、-print0を付加してやると
zaki@salva% find . -name "*txt" -print0 | od -c [~/tmp/path] 0000000 . / a b . t x t \0 . / a . t x 0000020 t \0 . / b . t x t \0 . / s u b / 0000040 a b . t x t \0 . / s u b / a . 0000060 t x t \0 . / s u b / b . t x t \0 0000100区切りが\0に変わる。
で、xargs -0 で本来「スペース/改行区切りで」ファイル名を拾う動作が、\0区切りになる、と。
zaki@salva% find . -name "*txt" -print0 | xargs -0 file [~/tmp/path] ./a b.txt: empty ./a.txt: empty ./b.txt: empty ./sub/a b.txt: empty ./sub/a.txt: empty ./sub/b.txt: empty
そもそもスペース込みのファイル名やディレクトリ名をつけるな、という話。
xargs(1)
find(1)
2011-02-06 Sun (他の年の同じ日: 2006)
前のエントリ/次のエントリにタイトル付加
2011-02-06-3 / カテゴリ: [perl][chalow] / [permlink]
アイテム毎ページの次へ/前へに、そのタイトルをつける。
テンプレ例
--- chalow.20110206 2011-01-23 16:42:29.715835927 +0900 +++ chalow 2011-02-06 03:59:16.342571765 +0900 @@ -763,15 +763,21 @@ my $ymdi_before; my $ymdi_after; + my $before_title; + my $after_title; if ($i > 1) { $ymdi_before = $ymd."-".($i-1); + $before_title = $ent->{$i-1}->{ho}; } elsif ($idx < @day_list - 1) { my $day_b = $day_list[$idx + 1]; $ymdi_before = $day_b."-".$cl->{all}->{$day_b}{curid}; + $before_title = $cl->{all}->{$day_b}->{$cl->{all}->{$day_b}{curid}}->{ho}; } if ($i != $ent->{curid}) { $ymdi_after = $ymd."-".($i+1); + $after_title = $ent->{$i+1}->{ho}; } elsif ($idx > 0) { my $day_a = $day_list[$idx - 1]; $ymdi_after = $day_a."-1"; + $after_title = $cl->{all}->{$day_a}->{1}->{ho}; } @@ -794,4 +800,6 @@ $t->param(back => $ymdi_before); $t->param(next => $ymdi_after); + $t->param(back_title => $before_title); + $t->param(next_title => $after_title); my $ccc = $item->{c}; $ccc =~ s!^<br />!!g;# ad hoc現在の処理対象アイテムのタイトル取得は
$t->param(header_text => $item->{ho};にあるので、特定のアイテムのタイトルは
$cl->{all}->{"YYYYmmdd"}->{x}->{ho};で取れる。
テンプレ例
--- cl.conf.20110206 2011-01-23 16:42:37.523566691 +0900 +++ cl.conf 2011-02-06 03:58:01.367043689 +0900 @@ -362,6 +362,6 @@ <div id="content"> <p class="calendar"><a href="<TMPL_VAR name=ym>.html"><TMPL_VAR name=ym></a> / <a href="<TMPL_VAR name=ymd>.html"><TMPL_VAR name=ymd></a></p> -<TMPL_IF name=back><a href="<TMPL_VAR name=back>.html">前のエントリ</a> / </TMPL_IF> -<TMPL_IF name=next><a href="<TMPL_VAR name=next>.html">次のエントリ</a></TMPL_IF> +<TMPL_IF name=back><a href="<TMPL_VAR name=back>.html">前のエントリ(<TMPL_VAR name=back_title>)</a> / </TMPL_IF> +<TMPL_IF name=next><a href="<TMPL_VAR name=next>.html">次のエントリ(<TMPL_VAR name=next_title>)</a></TMPL_IF> <!-- start:<TMPL_VAR name=ymdi> --> <div class="day">
AlarmManagerで単純にブロードキャストを投げるだけ
2011-02-06-2 / カテゴリ: [Java][Android] / [permlink]
__軽く__ググってみても、「指定Activityを起動」「BroadcastReceiverをextendsした自前レシーバで受ける」しか見つけられなかったので「特定Activityが生きてれば受ける、なければ無視」をお試し。
ちなみに、定期/定時処理の実装は以下の方法がある(ほかにも有るかも。知らないだけで)
するようなイメージみたい。(thanks! @amay077さん)
AlarmManagerはシステムレベルで動作するので、アプリの寿命と独立してるのがポイント。
指定時間にブロードキャストでなく、単にActivityを起動するだけなら、
AlarmManager.ELAPSED_REALTIME で「○msec後」に起動設定になる。
「Y年m月d日H時M分S秒に」の場合は、AlarmManager.RTC を使う
前記のAlarmManager#setは、指定時間に単に起動するのみ。
定期的に実行するにはAlarmManager#setRepeating()を使う。
キューに入ってるアラームを停止するにはcancel()
参考
Service(サービス)関連 mucchinのAndroid戦記
AlarmManagerで指定した時間に処理させる - Tech Booster
AlarmManager - 愚鈍人
Taosoftware: AlarmManager1 AndroidでCronみたいなことをするには
AlarmManagerの使用 - すにぺっと
ちなみに、定期/定時処理の実装は以下の方法がある(ほかにも有るかも。知らないだけで)
Timer | アプリで管理 |
AlarmManager | システム(android)で管理 |
AlarmManagerはシステムレベルで動作するので、アプリの寿命と独立してるのがポイント。
public final static String INTENT_ACTION = "alarmmgr_broadcast"; : : AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE); Intent intent = new Intent(INTENT_ACTION); PendingIntent pending = PendingIntent.getBroadcast(this, 0, intent, 0); long current = SystemClock.elapsedRealtime(); // 5秒後(current + 5*1000)にpending発動(1回きり) am.set(AlarmManager.ELAPSED_REALTIME, current + 5*1000, pending);このBroadcastを受けるには[2011-02-06-1]の例で。
指定時間にブロードキャストでなく、単にActivityを起動するだけなら、
Intent intent = new Intent(this, FooBar.class); PendingIntent pending = PendingIntent.getActivity(this, 0, intent, 0);こんな感じで。サービス起動もいけそう(getService()で)。
AlarmManager.ELAPSED_REALTIME で「○msec後」に起動設定になる。
「Y年m月d日H時M分S秒に」の場合は、AlarmManager.RTC を使う
Calendar cal = Calendar.getInstance(); cal.set(2011, 1, 6, 3, 0, 0); // 2011-02-06 03:00:00 の場合。monthは0オリジン(-1する) long next = cal.getTimeInMillis(); Log.d(TAG, "current: " + next); am.set(AlarmManager.RTC, next, pending);
前記のAlarmManager#setは、指定時間に単に起動するのみ。
定期的に実行するにはAlarmManager#setRepeating()を使う。
キューに入ってるアラームを停止するにはcancel()
am.cancel(pending);キャンセルは、Intentが同じ(filterEquals()がtrue)ものが対象らしい。
Remove any alarms with a matching Intent. Any alarm, of any type, whose Intent matches this one (as defined by filterEquals(Intent)), will be canceled.
AlarmManager#cancel
参考
Service(サービス)関連 mucchinのAndroid戦記
AlarmManagerで指定した時間に処理させる - Tech Booster
AlarmManager - 愚鈍人
Taosoftware: AlarmManager1 AndroidでCronみたいなことをするには
AlarmManagerの使用 - すにぺっと
レシーバおぼえがき(BroadcastReceiver)
2011-02-06-1 / カテゴリ: [Java][Android] / [permlink]
そのActivityがtopにいる場合にブロードキャストを受けるには。
(rergisterReceive()を複数叩いて複数のレシーバを受ける場合は必要)
おまけ
↑のInternalは別クラス(ブロードキャスト元)
投げる部分はこんな感じ。(適当)
public class FooBar extends Activity { : : // スレッドの通知を受けるためのレシーバ private final BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { Log.d(TAG, " onReceive(" + context + ", " + intent + ")"); if (intent.getAction().equals(Internal.INTENT_ACTION)) { Log.d(TAG, "intent val: " + intent.getIntExtra(Internal.INTENT_VAL, 0)); } } }; @Override public void onResume() { super.onResume(); Log.d(TAG, "onResume()"); // レシーバの登録 registerReceiver(mReceiver, new IntentFilter(Internal.INTENT_ACTION)); } @Override public void onPause() { super.onPause(); Log.d(TAG, "onPause()"); // レシーバの解除 unregisterReceiver(mReceiver); } :registerReceiver()第2引数でフィルタを設定しているので、onReceive()内でgetAction()でAction名をチェックしてるのはこの例では冗長。
(rergisterReceive()を複数叩いて複数のレシーバを受ける場合は必要)
おまけ
↑のInternalは別クラス(ブロードキャスト元)
投げる部分はこんな感じ。(適当)
public class Internal extends Activity { public final static String INTENT_ACTION = "internal_thread_broadcast"; public final static String INTENT_VAL = "internal_thread_val"; private int mCount = 0; // 中略 Thread thread = new Thread(new Runnable() { @Override public void run() { // TODO 自動生成されたメソッド・スタブ try { for (;;) { Thread.sleep(1000); mCount ++; Log.d(TAG, "running count("+ mCount + ")"); Intent intent = new Intent(INTENT_ACTION); intent.putExtra(INTENT_VAL, mCount); sendBroadcast(intent); } } catch (InterruptedException e) { // TODO 自動生成された catch ブロック e.printStackTrace(); } } }); thread.start(); // 後略
Referrer (Inside):
[2011-02-06-2]
2011-02-01 Tue (他の年の同じ日: 2005 2006 2007 2010)
シェルの起動
2011-02-01-2 / カテゴリ: [shell][Android] / [permlink]
% adb shelladbはSDK revision7まではtoolsの下にあったけど、revision8からはplatform-tools以下にあるので注意。(6→7だったかも知れん。うろ覚え)
エミュレータと実機、みたいに、複数のデバイスが接続されている場合は
% adb shell error: more than one device and emulatorとなってしまうので、
% adb devices List of devices attached emulator-5554 device HT********** deviceで一覧を出して、
% adb -s emulator-5554 shellと、シリアルナンバーでデバイスを指定してやる。
詳しくは
% adb -hで見れる。
なお、シェルコマンドは(sshのリモートコマンド実行の要領で)
% adb [-s serialnumber] shell [command [arg...]]で、一気に実行できる。
ちなみにシェルはsh(だよな?)。タイムマシンに乗った気分。
環境によって違うと思うけど、エミュレータ(2.2/デフォルトパラメタで作成)だと
# printenv printenv ANDROID_ROOT=/system LD_LIBRARY_PATH=/system/lib PATH=/sbin:/system/sbin:/system/bin:/system/xbin ASEC_MOUNTPOINT=/mnt/asec BOOTCLASSPATH=/system/framework/core.jar:/system/framework/ext.jar:/system/framework/framework.jar:/system/framework/android.policy.jar:/system/framework/services.jar ANDROID_BOOTLOGO=1 ANDROID_ASSETS=/system/app EXTERNAL_STORAGE=/mnt/sdcard ANDROID_DATA=/data ANDROID_PROPERTY_WORKSPACE=9,32768 # cat /proc/cpuinfo cat /proc/cpuinfo Processor : ARM926EJ-S rev 5 (v5l) BogoMIPS : 279.34 Features : swp half thumb fastmult vfp edsp java CPU implementer : 0x41 CPU architecture: 5TEJ CPU variant : 0x0 CPU part : 0x926 CPU revision : 5 Hardware : Goldfish Revision : 0000 Serial : 0000000000000000
desireII(2.2/ドノーマル)だと
$ printenv printenv ANDROID_ROOT=/system LD_LIBRARY_PATH=/system/lib PATH=/sbin:/system/sbin:/system/bin:/system/xbin ASEC_MOUNTPOINT=/mnt/asec BOOTCLASSPATH=/system/framework/core.jar:/system/framework/ext.jar:/system/framework/framework.jar:/system/framework/android.policy.jar:/system/framework/services.jar:/system/framework/com.htc.framework.jar:/system/framework/com.htc.android.pimlib.jar:/system/framework/com.htc.android.easopen.jar:/system/framework/com.scalado.util.ScaladoUtil.jar ANDROID_BOOTLOGO=1 ANDROID_ASSETS=/system/app EXTERNAL_STORAGE=/mnt/sdcard ANDROID_DATA=/data ANDROID_PROPERTY_WORKSPACE=10,65536 $ cat /proc/cpuinfo cat /proc/cpuinfo Processor : ARMv7 Processor rev 2 (v7l) BogoMIPS : 162.54 Features : swp half thumb fastmult vfp edsp thumbee neon CPU implementer : 0x51 CPU architecture: 7 CPU variant : 0x0 CPU part : 0x00f CPU revision : 2 Hardware : bravo Revision : 0083 Serial : 0000000000000000
などなど
エミュレータでパケットキャプチャ
2011-02-01-1 / カテゴリ: [command][network][Android] / [permlink]
ホストPCやサーバ側でキャプチャできない環境の場合、エミュ自身の内蔵tcpdumpでキャプチャ可能。
多分使う機会はホストがwindowsで、ホスト自身で動かしてるサーバへアクセスする際のキャプチャくらいかね。(リモートならEthereal使えば良し)
基本は
-s 0 は、未指定だとデフォルトキャプチャサイズが96bytesになり、キャプチャ漏れが発生するので、適当に指定すればよし。0指定だと65535byteになる。
-X は指定なしだと訓練されていないと読めない(笑)
port 80 の部分は、キャプチャのフィルタ条件。指定がないとidleでも結構パケットが飛んでいるので、見たいパケットが見えなくなる。
"port 80" で 80/TCP の全てのパケット
"host jp-z.jp" で、jp-z.jp との全パケット
"port 80 and host jp-z.jp" で↑のand
「コマンドラインじゃわからん!wiershark/etherealで見たいんだ!」な場合は
あとはググッてねん。
ちなみに停止の^Cで、シェルごとなぜか抜けてしまうので、PCのシェル(コマンドライン)上で
実機だとpermission deniedになる。うーん、rootな端末もあった方が良いのかも。
多分使う機会はホストがwindowsで、ホスト自身で動かしてるサーバへアクセスする際のキャプチャくらいかね。(リモートならEthereal使えば良し)
基本は
# tcpdump -s 0 -X port 80など。
-s 0 は、未指定だとデフォルトキャプチャサイズが96bytesになり、キャプチャ漏れが発生するので、適当に指定すればよし。0指定だと65535byteになる。
-X は指定なしだと訓練されていないと読めない(笑)
port 80 の部分は、キャプチャのフィルタ条件。指定がないとidleでも結構パケットが飛んでいるので、見たいパケットが見えなくなる。
"port 80" で 80/TCP の全てのパケット
"host jp-z.jp" で、jp-z.jp との全パケット
"port 80 and host jp-z.jp" で↑のand
「コマンドラインじゃわからん!wiershark/etherealで見たいんだ!」な場合は
# tcpdump -s 0 -w /mnt/sdcard/capture.cap port 80でキャプチャ結果をファイルへ出力できるので、DDMSのファイルエクスプローラで取り出して見ればOK
あとはググッてねん。
ちなみに停止の^Cで、シェルごとなぜか抜けてしまうので、PCのシェル(コマンドライン)上で
% adb -s emulator-5554 shell tcpdump -s 0 -w /mnt/sdcard/capture.cap port 80 and host jp-z.jpとした方が良いかも知れん。
実機だとpermission deniedになる。うーん、rootな端末もあった方が良いのかも。
前の月 / 次の月 / 最新
2013 : 01 02 03 04 05 06 07 08 09 10 11 12
2012 : 01 02 03 04 05 06 07 08 09 10 11 12
2011 : 01 02 03 04 05 06 07 08 09 10 11 12
2010 : 01 02 03 04 05 06 07 08 09 10 11 12
2009 : 01 02 03 04 05 06 07 08 09 10 11 12
2008 : 01 02 03 04 05 06 07 08 09 10 11 12
2007 : 01 02 03 04 05 06 07 08 09 10 11 12
2006 : 01 02 03 04 05 06 07 08 09 10 11 12
2005 : 01 02 03 04 05 06 07 08 09 10 11 12
2004 : 01 02 03 04 05 06 07 08 09 10 11 12
最終更新時間: 2013-05-02 16:12