Android Javaの正規表現の落とし穴

Androidで正規表現を使っていて、全角のパターンマッチで少しはまったのでメモ。

Javaでは他の正規表現エンジンと同様、POSIX文字クラスが利用できます。

if("Hello".match("^\\p{Alpha}+$")){
System.out.println("アルファベットだけ!");
}

続きを読む Android Javaの正規表現の落とし穴

Launch error: リモート VM に接続できませんでした

Android開発をしていて、ある時からアプリのデバッグ起動で次のようなエラーが出て固まるようになりました。


[2011-08-03 19:14:42 - com.example.testapp] ------------------------------
[2011-08-03 19:14:42 - com.example.testapp] Android Launch!
[2011-08-03 19:14:42 - com.example.testapp] adb is running normally.
[2011-08-03 19:14:42 - com.example.testapp] Performing com.example.testapp.First activity launch
[2011-08-03 19:14:42 - com.example.testapp] Automatic Target Mode: using device 'CB511J0W90'
[2011-08-03 19:14:42 - com.example.testapp] Uploading com.example.testapp.apk onto device 'CB511J0W90'
[2011-08-03 19:14:42 - com.example.testapp] Installing com.example.testapp.apk...
[2011-08-03 19:14:45 - com.example.testapp] 成功!
[2011-08-03 19:14:45 - com.example.testapp] Starting activity com.example.testapp.First on device CB511J0W90
[2011-08-03 19:14:45 - com.example.testapp] ActivityManager: Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.example.testapp/.First }
[2011-08-03 19:14:45 - com.example.testapp] Attempting to connect debugger to 'com.example.testapp' on port 8610
[2011-08-03 19:14:45 - com.example.testapp] Launch error: リモート VM に接続できませんでした

ポート8610番につなげない、と言われているので調べてみる。

C:\>netstat -an -p tcp 
 ~略~
 TCP    127.0.0.1:8600         0.0.0.0:0              LISTENING
 TCP    127.0.0.1:8601         0.0.0.0:0              LISTENING
 TCP    127.0.0.1:8602         0.0.0.0:0              LISTENING
 TCP    127.0.0.1:8603         0.0.0.0:0              LISTENING
 TCP    127.0.0.1:8604         0.0.0.0:0              LISTENING
 TCP    127.0.0.1:8605         0.0.0.0:0              LISTENING
 TCP    127.0.0.1:8606         0.0.0.0:0              LISTENING
 TCP    127.0.0.1:8607         0.0.0.0:0              LISTENING
 TCP    127.0.0.1:8608         0.0.0.0:0              LISTENING
 TCP    127.0.0.1:8609         0.0.0.0:0              LISTENING
 TCP    127.0.0.1:8610         0.0.0.0:0              LISTENING
 TCP    127.0.0.1:8612         0.0.0.0:0              LISTENING
 TCP    127.0.0.1:8613         0.0.0.0:0              LISTENING
 TCP    127.0.0.1:8614         0.0.0.0:0              LISTENING
 TCP    127.0.0.1:8615         0.0.0.0:0              LISTENING
 TCP    127.0.0.1:8616         0.0.0.0:0              LISTENING
 TCP    127.0.0.1:8620         0.0.0.0:0              LISTENING
 TCP    127.0.0.1:8621         0.0.0.0:0              LISTENING
 TCP    127.0.0.1:8622         0.0.0.0:0              LISTENING
 TCP    127.0.0.1:8623         0.0.0.0:0              LISTENING
 TCP    127.0.0.1:8624         0.0.0.0:0              LISTENING
 TCP    127.0.0.1:8626         0.0.0.0:0              LISTENING
 TCP    127.0.0.1:8627         0.0.0.0:0              LISTENING
 TCP    127.0.0.1:8629         0.0.0.0:0              LISTENING
 ~略~

と(やたらLISTENしているポートが多いのが気になるものの)ちゃんと開いているように見える。
ポートが空いてるのは確認できたが、firewallの影響を受けているかもしれないのでさらにしつこくjdbデバッガで調べてみる。

C:\>jdb -connect com.sun.jdi.SocketAttach:hostname=localhost,port=8610
uncaught java.lang.Throwable を設定しました
保留した uncaught java.lang.Throwable を設定しました
jdb の初期化中です...
> 

問題なくつなげたので一旦quitを入力して終了。
これで繋げなければJava VM側やネットワークの問題の可能性がありましたが、
これで原因はEclipseの可能性が高いということに。

改めてEclipseの設定を確認すると…

一般 → ネットワーク設定 → プロキシーのバイパスでプロキシが設定されていて、しかもlocalhost, 127.0.0.1 のプロキシが有効になってしまっていました。
これじゃ繋がるわけないわな。

アクティブ・プロバイダーが「ネイティブ」になっていて変更できなかったため「直接」に変更した上で上記2つのチェックを外した所無事解決。

WebViewのshouldOverrideUrlLoading()内でリダイレクト判定

WebView でリダイレクトではなくユーザクリックのみを飛ばしたい場合、

下記のようにするといいようです。

<pre><code>mWebView.setWebViewClient(new WebViewClient() { </code></pre>
<pre>	public boolean shouldOverrideUrlLoading(WebView view, String url) {
	    if(view.getHitTestResult().getType() &gt; 0){
	         // ユーザが自分でクリック参照したページ
	         return true;
	    } else {
	         // クリックされなかったのでリダイレクトとみなす。
	         return false;
	    }
	}
<span class="Apple-style-span" style="font-family: monospace;">}</span></pre>
参考:

Galaxy Tab 10.1(Google I/O Limited Edition)関係のメモ

Google I/O 2011 でもらった Samsung Galaxy Tab 10.1 LE について、はまったことのメモなど。

Twitterアプリでログインできない。

公式twitterクライアント, twicca, TweetDeck など何を使ってもログイン出来ないという現象が発生していました(ブラウザログインなら可)。

原因は初回起動時の設定で時刻の自動同期をオフにしていたことです。明示的に時刻設定するのをやめて自動同期をオンにし、タイムゾーン設定だけすればアプリからもログインできるようになります。

初期化設定画面でしかこの設定を変えられないため、再設定には「設定→プライバシー→出荷時の状態に戻す」で、一度工場出荷時の状態に戻す必要があります。

参考URL: http://forum.androidcentral.com/samsung-galaxy-tab-10-inch/84410-google-io-edition-tab-10-1-cant-log-number-apps.html

OS起動時に Fastboot USB download protocol でフリーズして何もできなくなった。

電源ボタンを押す時に、ボリュームボタンを押しているとfastbootブートモードやファームウェア書き換えモードに入ります。Upload Modeや Emergency Download Mode といった画面で固まってしまう事があります。

電源ボタンとボリュームボタン上下を同時に5秒以上の長押しすると直る事が多いようですが、どのボタンを押しても無反応なケースもあるため、対応方法を紹介します。

ちなみに無反応で電源ボタンも効かずバッテリーも外せずどうしようもなくなっても、電池切れになれば再起動できるから安心、と思いきや。xdaフォーラムによると、電池切れを待って再起動しても同じ画面に戻ってしまうようです…。

そんな場合の解決方法はこちら。

必要なもの

  • Galaxy 10.1(本体)
  • a href=”http://www.ubuntu.com/”>Ubuntu LinuxまたはMac OSXの入ったパソコン
  • Windowsしかない場合はUbuntuのダウンロードページにある、Windows installer を使うと簡単にインストールできます。

  • USBケーブル

解決手順

  1. Android SDKをインストール
  2. USBデバイス設定を行う
  3. /etc/udev/rules.d/*.rules に samsung 用のデバイス設定を記述します。Macの場合は設定不要です。
    /etc/udev/rules.d/51-android-samsung.rules

    SUBSYSTEM==”usb”, SYSFS{idVendor}==”04e8″, MODE=”0666″
    

    (イコール”=”は半角記号に直して下さい)

  4. fastboot で工場出荷状態にリセットし、再起動。
  5. SDKに含まれるfastbootプログラムを使います。fastbootはplatform-toolsフォルダ以下に含まれています。
    ※注意:fastboot -w で、端末中の全てのユーザデータが消えます。

    <SDKのパス>/platform-tools/fastboot -w
    <SDKのパス>/platform-tools/fastboot reboot
    

実行後「waiting for device」で固まる場合は端末がデバイスとして認識されていません。この場合はちゃんとUSB接続しているか、設定ファイルが正しいかを確認して下さい。

参考:

Android の隠しコード

Androidの隠し画面

Android スマートフォンの隠しコマンド一覧です。

コードを試すには電話番号の入力画面から、電話をかける要領で入力してください。

入力が完了すると自動で画面が切り替わります。

ほとんどの機種で利用出来ると思いますが、対応していないコードだった場合は入力文字がリセットされるだけで何もおこりません。また、性質上緊急電話モードでは利用できないようになっているようです。画面ロックしている場合はロック解除後に使用してください。

なお、熟練ユーザ向けの裏技的な機能ですので、操作を誤ると携帯が使えなくなるおそれがあります。知識のない方は決して使用しないでください。

*#06#

IMEI,MEIDなど携帯端末識別番号を表示します。

*#*#4636#*#*

電話端末情報、電波や電池の状態を表示します。

・携帯電話情報(Phone Information)

→ IMEI,電話番号,電波状況,pingテストなど。

・電池情報(Battery Information)

→電池残量、電圧、稼働時間など。

・充電池データ(Battery history)

→ バッテリ使用率の統計。

・使用統計情報(Usage statistics)

→ アプリごとの起動回数、使用時間などの統計。

・WiFi情報(Wifi information)

→ WiFiのAPIを直接実行できる。

*#*#8255#*#*

GTalkサービスモニターを開きます。

こちら他にも隠しコードが紹介されています。機種依存で動かないコードや工場リセットなどの危険なコードもあるので実行する場合はくれぐれも注意してください。

あわせて読みたい

docomoな方向けにこんな記事も書きました。

知らないと損!なドコモWIFI の使い方(PC/IPHONE/ANDROID)
いつも通信制限で困ってる方、外でのインターネット環境にお困りの方にはお役立ち情報です。

裏技つながりで、こういうのもあります。

ドコモユーザ必見、2年に1回、必ずdポイントを大量ゲットできる裏技

よければ読んでみてくださいね。

参考:

AsyncTaskでブレークポイントを指定する時の注意点

AsyncTask の中でブレークポイントを設定する場合は、doInBackground() の最初で

android.os.Debug.waitForDebugger();

を呼ぶ必要があります。
 
呼ばないとブレークポイントを無視してしまいます。
 
デバッガが居なくても以外もwaitForDebugger()で処理を停止してしまうので、
デバッグ実行が終わったらちゃんとコメントアウトしましょう。
 
#謎の不具合で丸一日はまった…
 
参考:
Debug#waitForDebugger())

Androidマーケットで公開キャリアを制限する

Android マーケットではSIMカードのキャリアで公開対象をフィルタリングすることができます。
 
■制限している例(2011-04-12現在):
– S-1バトル(Softbank限定)
– Skype(公開当初はau限定だった)
– spモードメールアプリ(NTTドコモ限定)
 
方法は簡単で、デベロッパーコンソール(Developer Console)からアプリapkをアップロードする際に以下の手順で設定します。
 
1.公開設定のオプション(Publishing options)内の「すべての国(All Country)」のチェックを外す。
2.制限対象国(日本)のリンクをクリック。
3.公開したい携帯キャリアだけにチェックをいれる。
 
設定したスクリーンショットがこちらになります。


 
簡単ですね。
その他のフィルタリング設定についてはマニュアルのMarket Filter(日本語訳)の項目が参考になります。
 
参考:
carrier targeting of apps(Android Developers)

MercurialEclipse+ADTで not in root エラー

ある時からMercurial Eclipse(v1.8)でコミットをしようとするとnot under rootというエラーが出るようになりました。
原因をググってみるとどうやら Android のライブラリプロジェクトとメインプロジェクトの両方でMercurialを使っていると出るらしい。
解決方法はAndroidライブラリの依存チェックを外すか、どちらかのリポジトリを切断するかで、どちらも場当たり的なのが悩ましい…。
 
参考として、スタックトレースは以下の通りでした(MercurialEclipse バージョン 1.8.0.v201103281715 で確認)

!ENTRY com.vectrace.MercurialEclipse 4 0 2011-04-11 12:24:47.074
!MESSAGE 中断: c:\path\to\android_project_dir not under root. コマンド行: c:\path\to\android_library_project_dir\hg -y status -marduc — c:\path\to\android_project_dir, error code: -1
!STACK 1
中断: D:\usr\eclipse\net.canp.android.purigaget not under root. コマンド行: D:\usr\eclipse\net.canp.android.common\hg -y status -marduc — D:\usr\eclipse\net.canp.android.purigaget, error code: -1
at com.vectrace.MercurialEclipse.commands.AbstractShellCommand.executeToStream(AbstractShellCommand.java:405)
at com.vectrace.MercurialEclipse.commands.AbstractShellCommand.executeToBytes(AbstractShellCommand.java:348)
at com.vectrace.MercurialEclipse.commands.AbstractShellCommand.executeToString(AbstractShellCommand.java:548)
at com.vectrace.MercurialEclipse.commands.AbstractShellCommand.executeToString(AbstractShellCommand.java:544)
at com.vectrace.MercurialEclipse.commands.HgStatusClient.getStatusWithoutIgnored(HgStatusClient.java:154)
at com.vectrace.MercurialEclipse.team.cache.MercurialStatusCache.updateStatusInRoot(MercurialStatusCache.java:1333)
at com.vectrace.MercurialEclipse.team.cache.MercurialStatusCache.refreshStatus(MercurialStatusCache.java:1287)
at com.vectrace.MercurialEclipse.team.cache.MercurialStatusCache.access$0(MercurialStatusCache.java:1273)
at com.vectrace.MercurialEclipse.team.cache.MercurialStatusCache$ProjectUpdateJob.updateProject(MercurialStatusCache.java:144)
at com.vectrace.MercurialEclipse.team.cache.MercurialStatusCache$ProjectUpdateJob.run(MercurialStatusCache.java:126)
at org.eclipse.core.internal.jobs.Worker.run(Worker.java:54)
!SUBENTRY 1 com.vectrace.MercurialEclipse 4 -1 2011-04-11 12:24:47.074
!MESSAGE 中断: c:\path\to\android_project_dir not under root. コマンド行: c:\path\to\android_library_project_dir\hg -y status -marduc — c:\path\to\android_project_dir

 
参考:
MercurialEclipseでちょっと困った(Naga Blog)

MapView で InflateException 例外が出る原因

com.google.android.maps.MapView 周りで

android.view.InflateException: Binary XML file line #103: Error inflating class com.google.android.maps.MapView
<
 <
のようなエラー等が出る場合、次の原因が考えられます。
 
– MapView を使う Activity で MapActivity を継承していない。
 
– AndroidManifest.xml の <application> タグ内で

<uses-library android:name=”com.google.android.maps” />

 を定義していない。

SQLiteException – file is encrypted or is not a database

SQLiteOpenHelper で表題の例外が出てしまったので対策メモ。
 LogCat:

02-22 17:26:58.351: ERROR/Database(23305): Failed to setLocale() when constructing, closing the database
02-22 17:26:58.351: ERROR/Database(23305): android.database.sqlite.SQLiteException: file is encrypted or is not a database
02-22 17:26:58.351: ERROR/Database(23305): at android.database.sqlite.SQLiteDatabase.native_setLocale(Native Method)
02-22 17:26:58.351: ERROR/Database(23305): at android.database.sqlite.SQLiteDatabase.setLocale(SQLiteDatabase.java:1751)
02-22 17:26:58.351: ERROR/Database(23305): at android.database.sqlite.SQLiteDatabase.<init>(SQLiteDatabase.java:1701)
02-22 17:26:58.351: ERROR/Database(23305): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:739)
02-22 17:26:58.351: ERROR/Database(23305): at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:761)
02-22 17:26:58.351: ERROR/Database(23305): at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:754)
02-22 17:26:58.351: ERROR/Database(23305): at android.app.ApplicationContext.openOrCreateDatabase(ApplicationContext.java:497)
02-22 17:26:58.351: ERROR/Database(23305): at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:193)
02-22 17:26:58.351: ERROR/Database(23305): at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:98)
// 以下アプリ内の getWritableDatabase() 参照箇所に続く

原因を調べたところ、どうもSQLiteのデータベースファイルが破損されているようなので、接続時にエラーの時はファイルをクリアして再接続するようにオーバーライド実装して対応しました。

@Override
public synchronized SQLiteDatabase getWritableDatabase() {
        try {
                return super.getWritableDatabase();
        } catch (SQLiteException e) {
                final File file = mContext.getDatabasePath(DATABASE_NAME);
                file.delete();
                return super.getWritableDatabase();
        }
}
 
@Override
public synchronized SQLiteDatabase getReadableDatabase() {
        try {
                return super.getReadableDatabase();
        } catch (SQLiteException e) {
                final File file = mContext.getDatabasePath(DATABASE_NAME);
                file.delete();
                return super.getReadableDatabase();
        }
}

参考:
http://d.hatena.ne.jp/esmasui/20091103/1257276598