2010/12/26

SEMC HSUSB Device ドライバがなくなった!

Xperia を 2.1 にアップデートしたら、USBデバッグモードで接続できなくなってしまいました。
デバイスマネージャを開いてみると、
SEMC HSUSB Device
というデバイスのドライバがないようです。

で、ドライバはどこにあるのかと探し回ったら、実は Windows Update で提供されていました。
  1. IE で
    ツール → Windows Update
  2. 「カスタム」を選択
  3. 追加選択(ハードウェア)
  4. Sony Ericsson Sony Ericsson sa0101 ADB Interface Driver を選択
  5. 更新プログラムの確認とインストール

2010/12/23

マイアップロード (com.google.android.apps.uploader) が予期せず停止しました

@Xperia (android 2.1)

Xperia で Picasa に写真をアップロードしてる最中に削除したら、不整合が起こったらしく、アップロードしようとするたびに、「マイアップロード(com.google.android.apps.uploader) が予期せず停止しました。やり直してください。」というエラーが出て、落ちてしまうようになってしまった…

こういう時の修正方法は、
  1. 設定 → アプリケーション

  2. アプリケーションの管理

  3. メニュー → フィルタ

  4. すべて

  5. リストから「マイアップロード」を探し出して、データを消去

これで、とりあえずは動くようになったけど、当然アップロード中のファイルは消えてしまいました。
バックアップとってたから良かったけど、危ない危ない。

2010/12/18

XPERIA を KBC-L2AS で充電する

XPERIA を買ってから eneloop KBC-L2A (最近の型番は KBC-L2AS) を充電に使っています。
(Amazon で見ると、「Xperiaには対応しておりません。」って書いてありますが、問題なく使えます。昔は特殊なケーブルが無いと駄目だったのですが、OSが2.1になってからは問題なく充電できるようです。)

最近気づいたのですが、一度、電池が全く無くなってから充電しようとしても充電できないようです。
ちょっと観察してみると、Sony Ericsson のロゴが出た直後に、eneloop の出力が落ちてしまいます。
詳しい原因はわかりませんが、多分、出力電流が定格を上回ってしまうんじゃないでしょうか。
そこで、eneloop の出力が落ちた直後、すぐボタンを押して復帰させると充電を続けることが出来ました。

ところが、そのまま放っておくと、いつの間にか充電が止まってしまいます。
もう一度、最初から観測してみると、一度復帰させてから約1分後、もう一度、同じ現象が起こっているようです。
再度復帰させれば、次は何とかフル充電が可能になりました。

これって、もしかすると個体差とかあるんでしょうかねぇ。
だとすると、人によっては何の問題も無く充電できたりするのでしょうか?


12/25 追記
同じことをしてみたのですが、今回は問題なく最初から充電できました。
前回は電池がなくなってから一晩近く放置した後だったので、充電開始した直後のLEDは赤だったと思うのですが、今回は電池が無くなってすぐ充電を開始したので、LEDは黄色でした。
その違いが効いているのかどうかはわかりませんが。
あとは、温度が変わったとか…?

2010/12/04

ExifTool.exe の簡単な使い方 - 編集編

for Windows

ExifTool をダウンロードして、使えるようにするところまでは、ExifToolの簡単な使い方 - 表示編 に書いたので、参考にしてください。

EXIF の値を変更するのはとても簡単です。
以下のように、TAGに対して値を入れてあげればオッケー。
$ ./exiftool.exe -TAG=VALUE hoge.jpg

たとえば、画像に緯度経度情報を入れる場合は、以下のようにします。
$ ./exiftool.exe -gpslatitude=35.368475 -gpslongitude=138.721061 hoge.jpg

情報を消す場合は、=の後ろを空欄にします。
その他の書き方は、サイトにあった表がわかりやすいので訳してみました。
SyntaxResult
-TAG=TAG を削除します
-all=全てのメタ情報を削除します
-GROUP:TAG=グループのTAGを削除します
-GROUP:all=グループ中の全てのメタ情報を削除します
-[GROUP:]TAG=VALUETAG に VALUE を代入します
-[GROUP:]TAG+=VALUETAG に VALUE を追加します(リストタイプのみ)
-[GROUP:]TAG-=VALUETAG から VALUE を削除します
-[GROUP:]TAG<=FILETAG にファイルから値を入れる
[GROUP:] は正しいグループであるときのみ

グループはタグをカテゴライズするのに使用するようで、正しいタグとの組み合わせでないと機能しません。ネームスペースみたいなもんでしょうか?ちょっと良くわからないです…グループを使いこなすのはなかなか難しそうですね…
ちなみに、グループ一覧は以下にあります。大量です。
http://www.sno.phy.queensu.ca/~phil/exiftool/#groups


また、タグ一覧は以下からたどれます。
http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/index.html
ぱっと見、100くらいあるんですが、実はインデックスです。クリックするとさらに大量に出てきます。
こんなに使いこなせん…

ExifTool.exe の簡単な使い方 - 表示編

for Windows

最近、使っていなかった ExifTool
久しぶりに使用する機会があったのだけど、いつの間にか Version 8.41 になってる。
使い勝手は以前とほぼ同じ。でも、細かくレベルアップしてるみたい。
たとえば、日本語に対応してるとか!

で、大分前に書いた記事をリライトしてみます。

まず、http://www.sno.phy.queensu.ca/~phil/exiftool/ より、Windows Executable をダウンロード。
そのファイルを解凍すると、exiftool(-k).exe という変な名前のファイルが出来る。
なんだこりゃ?
と思ってヘルプを読むと、()の中身は exiftool.exe に与えるオプションだという。
-k は表示の後にポーズをかけるオプション。

ためしに、exiftool(-k).exe に画像ファイルをドラッグ・アンド・ドロップすると、確かに EXIF 情報が表示された。
そして、exiftool.exe とリネームしてから画像ファイルをドラッグ・アンド・ドロップすると、一瞬ウィンドウが表示されるだけ。
なるほど。面白い仕様だ。

ちなみに、サイトにある表を勝手に訳してみると、こんな感じ。
ファイル名を書き換えるだけで、結構いろいろ出来ちゃったりする。
Executable NameOperation
exiftool(-k).exeメタ情報を表示して、ポーズする
exiftool(-k -a -u -g1 -w txt).exe詳細メタ情報を .txt ファイルに出力する
exiftool(-k -o %d%f.xmp).exeXMPサイドカーファイルを作成する
exiftool(-copyright='Phil Harvey').exeコピーライトを付加


でも、いちいちファイル名を書き換えるのは面倒くさいので、やっぱりコマンドラインで使うのが一番です。
というわけで、exiftool.exe にリネーム。

情報を表示させるには、
$ ./exiftool.exe hoge.jpg
って打ってやればいい。
ちなみに、日本語でも表示できるということなので、
$ ./exiftool.exe -lang ja hoge.jpg
って打ってみた。見事に文字化け…
UTF8 で出力するみたいで、ターミナルによっては文字化けるみたいですな。
(-charset で文字コードを変更できるって書いてありますが、日本語はUTF8だけみたい。)

日本語で見たい場合は、
$ ./exiftool.exe -lang ja -h hoge.jpg > hoge.html
とかやって、一度 .html ファイルで保存してから、ブラウザで開いてみるのが良いかと思います。

ExifTool を使った編集の仕方は ExifTool の簡単な使い方 - 編集編 に書いてみました。

2010/12/02

Twitter のタイムラインを表示する for Blogger

私の趣味のブログ(Team Hige)では、記事の上に Twitter のタイムラインを表示しています。デザイン的にイマイチではありますが、それはさておき、これを表示するための方法を書いておきます。

まず、Blogger にログインしておきます。
その状態で Twitter の ウィジェット サイトに行き、表示するウィジェットを作ります。サイトに合わせてデザインなどを修正したあと、「完了&コード取得」を押すと、以下のような "Add to Blogger" ボタンが出てくるので、簡単に Blogger のガジェットとして追加することができます。

ちなみに、私のサイトではヘッダ・フッタを消して、 Follow me ボタンを表示しています。
フッタ等を消す方法は Twitterウィジェットが生成するタグとCSS (もげる人) を参考にさせてもらいました。
このとき、Blogger では <style> タグの中に改行が入ってしまうと、うまく動かないようですので、ご注意ください。
以下に実際に使用しているコードを挙げておきます。
<style type="text/css">#twtr-widget-1 .twtr-hd, #twtr-widget-1 .twtr-ft { display: none; }</style>
<script type="text/javascript" src="http://widgets.twimg.com/j/2/widget.js"></script>
<script type="text/javascript">
new TWTR.Widget({
  version: 2,
  type: 'profile',
  rpp: 3,
  interval: 6000,
  width: 468,
  height: 120,
  theme: {
    shell: {
      background: '#ffffff',
      color: '#000000'
    },
    tweets: {
      background: '#ffffff',
      color: '#000000',
      links: '#3778cd'
    }
  },
  features: {
    scrollbar: false,
    loop: false,
    live: false,
    hashtags: true,
    timestamp: true,
    avatars: true,
    behavior: 'all'
  }
}).render().setUser("yusuke_n").start();
</script>
<div style="display:block;text-align:right;">
<a href="http://www.twitter.com/yusuke_n"><img src="http://twitter-badges.s3.amazonaws.com/follow_me-b.png" alt="Follow yusuke_n on Twitter"/></a>
</div>

2010/12/01

IE で google-code-prettify を使うと改行されない

このサイトでは google-code-prettify を利用してコードに色をつけています。
google-code-prettify は非常に便利なのですが、IEで表示すると改行されないという問題があります。(使用しているバージョンは prettify-21-Jul-2010.zip)

どうも、過去のバージョンでは表示には影響がなく、コピーしたときに改行が反映されないという問題だったようですが、バージョン21では、表示さえ崩れてしまいます。
さすがにこれでは困るので、google-code-prettifyを適用したソースをIEでコピーしたときに改行を反映させたい を参考に prettify.js の 1458行目を以下のように修正しました。

cs.innerHTML = (/*@cc_on!@*/false) ? newContent.replace(/\x0D\x0A|\x0D|\x0A/g,'<br />\n\r') : newContent;

やはり、バージョン21では<br />タグは使わず改行コードのみ出力しているようなので、置換の正規表現を修正してやる必要がありました。
また、コピーしたら改行がなくなる問題は解決していません。onbeforecopy というイベントを使えば解決できるっぽいですが、IEのためにそこまでするのもねぇ…
コードをコピーして使いたい人 = プログラマー = IEなんて使ってない
ということで、対応しないってのはどうでしょう?無理やりすぎ??んー

ちなみに、Google としても「仕様を満たしていないブラウザなんぞサポートしない」ってことなんでしょうか?
気持ちはわかります。超わかります。
でも、まだまだユーザの多いブラウザなので、正式対応してほしいものです。

2010/11/28

OnGestureListener の処理順

Android の Activity には onTouchEvent というのがあって、シングルタップを捕まえることができます。しかし、ダブルタップのような複雑なイベントを捕まえる機能はデフォルトでは備わっていません。

そういった複雑な動作を捕まえるためには、Activity に OnGestureListener, OnDoubleTapListener というインターフェースを実装してやります。
このとき、どのイベントがどのタイミングで呼ばれるのか調べるために、以下のようなコードを書いてみました。

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.GestureDetector.OnDoubleTapListener;
import android.view.GestureDetector.OnGestureListener;
import android.view.GestureDetector;
import android.view.MotionEvent;

public class Main extends Activity implements OnGestureListener, OnDoubleTapListener {

    private GestureDetector gestureDetector;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        gestureDetector = new GestureDetector(this, this);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent e) {
        super.dispatchTouchEvent(e);
        gestureDetector.onTouchEvent(e);
        return onTouchEvent(e);
    }

    public boolean onSingleTapConfirmed(MotionEvent e) {
        Log.i("test", "onSingleTapConfirmed");
        return false;
    }

    public boolean onDoubleTap(MotionEvent e) {
        Log.i("test", "onDoubleTap");
        return false;
    }

    public boolean onDoubleTapEvent(MotionEvent e) {
        switch (e.getAction()) {
        case MotionEvent.ACTION_DOWN:
            Log.i("test", "onDoubleTapEvent DOWN");
            break;
        case MotionEvent.ACTION_MOVE:
            Log.i("test", "onDoubleTapEvent MOVE");
            break;
        case MotionEvent.ACTION_UP:
            Log.i("test", "onDoubleTapEvent UP");
            break;
        default:
            Log.i("test", "onDoubleTapEvent OTHER");
            break;
        }
        return false;
    }

    public boolean onDown(MotionEvent e) {
        Log.i("test", "onDown");
        return false;
    }

    public void onShowPress(MotionEvent e) {
        Log.i("test", "onShowPress");
    }

    public boolean onSingleTapUp(MotionEvent e) {
        Log.i("test", "onSingleTapUp");
        return false;
    }

    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
            float distanceY) {
        Log.i("test", "onScroll");
        return false;
    }

    public void onLongPress(MotionEvent e) {
        Log.i("test", "onLongPress");

    }

    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
            float velocityY) {
        Log.i("test", "onFling");
        return false;
    }
}

Xperia (Android 2.1) で試した結果、以下のようになりました。

2010/11/27

onDoubleTap と onDoubleTapEvent の違い

Android の Activity には onTouchEvent というのがあって、シングルタップを捕まえることができます。しかし、ダブルタップのような複雑なイベントを捕まえる機能はデフォルトでは備わっていません。

そういった複雑な動作を捕まえるためには、Activity に OnGestureListener, OnDoubleTapListener というインターフェースを実装してやります。
(具体的な使い方は Google Map でダブルタップズーム for Android を参考にしてください)

ところで、 OnDoubleTapListener には OnDoubleTap と OnDoubleTapEvent という2つのメソッドが存在しますが、最初どういう違いがあるのか良くわからなかったので、ちょっと調べてみました。
って言っても、コメント読んだだけですが :-)


OnDoubleTap の ToolTip には、
Notified when a double-tap occurs.
と書いてあります。直訳すると、
ダブルタップされた時に通知されます
って感じでしょうか。そのままですね。


OnDbouleTapEvent の ToolTip には、
Notified when an event within a double-tap gesture occurs, including the down, move, and up events.
と書いてあります。
ダブルタップ中にイベントがおこると通知されます。ダウン、移動、アップを含みます
という感じでしょうか。
実際、OnDbouleTapEvent をログで捕まえると、一回のダブルタップで4,5回のイベントを捕まえる事ができます。
OnDbouleTapEvent が呼ばれた起因を調べるには、以下のように MotionEvent の getAction メソッドを使えば可能です。
public boolean onDoubleTapEvent(MotionEvent e) {
        switch (e.getAction()) {
        case MotionEvent.ACTION_DOWN:
            Log.i("Test", "Action Down.");
            return true;
        case MotionEvent.ACTION_UP:
            Log.i("Test", "Action Up.");
            return true;
        case MotionEvent.ACTION_MOVE:
            Log.i("Test", "Action Move.");
            return true;
        default:
            Log.i("Test", "Action Other.");
            return true;
        }
    }
2回タップした後に、指を離さず、ちょっと動かしてみたときのログは以下のようになりました。
11-26 23:43:57.286: INFO/Test(326): Action Down.
11-26 23:43:57.406: INFO/Test(326): Action Move.
11-26 23:43:57.447: INFO/Test(326): Action Move.
11-26 23:43:57.476: INFO/Test(326): Action Move.
11-26 23:43:57.536: INFO/Test(326): Action Move.
11-26 23:43:57.576: INFO/Test(326): Action Move.
11-26 23:43:57.607: INFO/Test(326): Action Move.
11-26 23:43:57.827: INFO/Test(326): Action Up.

2010/11/28 追記
その他のイベントも、どのような順番で処理されるのか調べてみました。
OnGestureListener の処理順

2010/11/20

Google Maps でダブルタップズーム for Android

Android で Map を扱うアプリを作っていると、デフォルトで入っている Google Map のようにダブルタップでズームして欲しいと思います。
ところが、なかなかこれが難しいのです。
調べてみると、皆さんなかなか苦労しているようです。

Android: MapActivityでダブルタップする (パトラッシュさん)

そこで、もう少しシンプルなやり方が無いか考えてみました。
ポイントは、onDoubleTapEvent ではなく onDoubleTap を使うことと、ZoomControl を連続タップした時にダブルタップとして認識されないようにする方法です。

import com.google.android.maps.MapActivity;
import com.google.android.maps.MapView;

import android.graphics.Rect;
import android.os.Bundle;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.GestureDetector.OnDoubleTapListener;
import android.view.GestureDetector.OnGestureListener;

public class Main extends MapActivity implements OnGestureListener, OnDoubleTapListener {
    private MapView mapView;
    private GestureDetector gestureDetector;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        mapView = (MapView)findViewById(R.id.mapView01);
        mapView.setBuiltInZoomControls(true);

        gestureDetector = new GestureDetector(this, this);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent e) {
        super.dispatchTouchEvent(e);

        // ZoomController の 画面上の座標を取得する
        int[] offset = new int[2];
        mapView.getZoomButtonsController().getContainer().getLocationOnScreen(offset);
        // ZoomController 中の Hit領域の矩形を取得する
        // (Hitとは領域は + - が表示されている領域のこと)
        Rect rect = new Rect();
        mapView.getZoomButtonsController().getZoomControls().getHitRect(rect);
        // 画面上の座標に変換
        rect.offset(offset[0], offset[1]);
        if (!rect.contains((int)e.getRawX(), (int)e.getRawY())) {
            // タッチされた場所が、Hit領域に含まれていなければ
            gestureDetector.onTouchEvent(e);
        }

        return onTouchEvent(e);
    }

    public boolean onDoubleTap(MotionEvent e) {
        // ズーム処理
        mapView.getController().zoomInFixing((int)e.getX(), (int)e.getY());
        return true;
    }

    // ・・・
    // その他の 自動生成されたメソッド・スタブ に関しては省略

}

以下、簡単な解説です。

2010/11/04

ローカルに保存しちゃったメールを Gmail にインポートする (続き)

先日、ローカルに保存しちゃったメールを Gmail にインポートする (送受信日はそのまま) という記事を書いたのだけれど、やっぱり皆さん考えることは同じのようで、同じような事をしているサイトを見つけてしまいました。かつ、もっと簡単に…

GMailにメールを完全移行する(http://gmail.1o4.jp/import.html)

確かに、ローカルのメールをインポートできるメールサービスを使えば簡単に出来るよなぁ…
もっとちゃんと検索してからやればよかった(笑)

しかし、この「Gmailの使い方!」ってサイトすごいなぁ。

2010/11/02

ローカルに保存しちゃったメールを Gmail にインポートする (送受信日はそのまま)



11/4 追記 → http://kokufu.blogspot.com/2010/11/gmail_04.html


最近、スパムメールの量が一気に増えました。
スパムフィルタはかけているので、別に構わないと言えば構わないのですが、以前から Gmail に移行しようと思っていたところだったので、ちょうど良い機会だから乗り換えることにしました。

ところが、Gmail はローカルに保存しちゃったメールをインポートする術を提供してくれてないようなのです。(2010年10月現在)
しかし、今までのメールを破棄はしたくはないのです。
調べてみると Google Mail Loader (http://www.marklyon.org/gmail/) を使うと既存のメールを Gmail に送ることができるということがわかりました。しかし、メールの送受信日時が現在になってしまうという問題があるのです。出来れば、送受信日時はオリジナルを維持して欲しいものです。

そこで、ローカルに保存しちゃったメールを、もう一回サーバに上げてインポートさせることで、送受信日時を維持したままGmailにアップすることにしました。
以下、その手順を簡単にまとめますが、結構面倒くさいです。
自分でサーバを建てられる人以外にはお勧めしません。ご注意ください。

私は VMWare上に Windows XP をインストールし、Mercury Mail をメールサーバとして使用しましたが、他のメールサーバでも大丈夫だと思います。(保証はしかねますが)

  1. VMWare を準備する
    本質じゃないので割愛
    ネットワーク接続はブリッジ、物理ネットワーク接続の状態を複製するのチェックボックスを外しておくと、VMWare上のOSに個別のIPアドレスが割り振られるので、設定が楽になります。

  2. Mercury Mail インストール
    以下をインストールしました。
    Mercury/32 Mail Transport System for Win32 and NetWare Systems v4.72
    http://www.pmail.com/

    設定方法などは、以下のサイトなどに詳しく載ってます。
    基本的には、SMTP と POP3 サーバーが動いていればオッケーなので、プラグインなどはインストールしなくても良いです。
    http://mizushima.ne.jp/Windows/Mail/Mercury/Mercury.php
    http://www.aconus.com/~oyaji/mail2/mercurymail.htm

  3. 110番と25番のポートを開けます
    ファイヤーウォールの設定でポートを開けます
    私は VMWare 上に新規の環境を作ったので、ファイヤーウォール無効にしてしまいました。そっちの方が手っ取り早かったので。あまりお勧めはしません。

    ルータを使っている場合は、ルータのポート転送設定もしてやる必要があります。

    ここまで来たら、メールサーバとして動作するはずですので、一度、外部のメーラーからアクセスしてみて、メールサーバとして動作するか確認してみると良いでしょう。

  4. 既存のメールを eml ファイルとしてエクスポート
    Mercury Mail は EML形式でファイルを管理しているようです。
    大抵のメーラーは eml ファイルをエクスポートする機能がついていると思うので、それを利用して、emlを吐き出します。
    UNIX系のメールサーバはmbox形式かもしれません。

  5. ファイル名を変換する
    Mercury Mail は eml ファイルを .cnm ファイルとして持つ仕様のようなので、拡張子 .eml を .cnm に変換します。
    かつ、Mercury Mail は日本語ファイル名が使えません。ファイル名を半角英数字に変換する必要もあります。
    参考までに、私が作ったスクリプトを挙げておきます。
    #!/bin/sh
    
    j=0
    for i in *.eml
    do
        echo "$i" "${j}.CNM"
        mv "$i" "${j}.CNM"
        j=`expr $j + 1`
    done

  6. サーバにアップする
    Mercury Mail の場合、C:\MERCURY\MAIL\username\ に先ほど作成した xxxx.CNM をコピーすればオッケーです。

  7. Gmail にインポート
    gmail の 「アカウントとインポート」「メッセージと連絡先のインポート」からインポート情報を入れます



    個人的には、インポートしたメールには新規のラベルをつけておいた方が良いと思います。
    ラベルを外すのは簡単ですが、つけるのは意外と面倒です。
    インポート開始を押せば、メールの取り込みが始まります。トラフィックに負担をかけないためだと思いますが、ゆっくり取り込みます。気長に待ちましょう。

2010/08/08

com.google.process.gappsが予期せず停止しました

xperia で Gmail 起動すると、「com.google.process.gappsが予期せず停止しました。やり直してください」って出るようになった。
受信トレイを表示させると必ず出る。やばい…

  1. とりあえず再起動してみた
    やはり駄目
  2. 設定 → アプリケーションの設定 → アプリケーションの管理 → Gmailストレージ → データを消去
    やはり駄目
  3. 初期化
    やはり駄目…
  4. PC使って、昨日来たメールを全削除してみた
    なんと復活!!

初期化してみる前に、Google のアカウントを別のものにして試してみるべきだった…
大失敗。
まー、とりあえず直ったから良しとしよう。