Javaでログを取る際にはLog4jなどの高機能なロギングライブラリを使う場合が多い。
高機能なロギングライブラリの便利なところは、ログを出力した際に出力したログがどのファイルのどの行で出力されたかも記録できるところだ。
この機能があるとログからバグのありかを探す場合や、ログの整理したい場合に作業が楽になる。

Android開発でも同じようにログを取りたいが、Log4jは残念ながらAndroidには対応していない。Androidでも使えるロギングライブラリにMicrolog4Androidなどがあるが、残念ながらファイル名と行番号を出力する機能が無い。

無いなら作ればいいやと言うことで、ファイル名と行番号付きでログを吐ける簡単なロガークラスを作成した。ファイルのありかはこちら

Log.dの代わりに次のようにして使う。

Logger.d("ほげほげ");
Logger.d("ふがふが(例外付き)", e);
Logger.e("エラーですよ!!!", e);

次のような感じでファイル名と行番号付きでLogCatに吐くことが出来る。省略したけれどスタックトレースも吐ける。例外チェーンはとりあえず2階層まで対応。

 (HogeFragment.java:201) - テスト
(HogeFragment.java:110) - ですよ
(FugaManager.java:172) - なんと!

ファイル名と行番号を取得するのは割とコストがかかるので、ログを出力するのはデバッグ時のみにしておくほうがよさげ。

AndroidでSDカードが抜き差しされたことを検知する方法。

MEDIA_MOUNTEDとMEDIA_UNMOUNTEDのIntentがブロードキャストされるので、それを受信すればok。

AndroidManifest.xmlに次のように記述する。

<receiver android:name="SDCardMountReceiver">
  <intent-filter>
    <action android:name="android.intent.action.MEDIA_MOUNTED"></action>
    <data android:scheme="file" />
  </intent-filter>
</receiver>
<receiver android:name="SDCardUnmountReceiver">
  <intent-filter>
    <action android:name="android.intent.action.MEDIA_UNMOUNTED"></action>
    <data android:scheme="file" />
  </intent-filter>
</receiver>

BroadcastReceiver を実装する。

public class SDCardMountReceiver extends BroadcastReceiver {
  @Override
  public void onReceive(Context context, Intent intent) {
    Log.d("Test","SDカードがマウントされました。");
  }
}

MEDIA_UNMOUTED時のBroadcastReceiverは省略。

Ubuntuはデフォルトでファイアウォールが設定されていない。
Ubutnuではufwを用いて簡単にファイアウォールを設定することができるので、メモを残しておく。

ufwのインストール

デフォルトで入っていると思うけれど、入っていない場合はインストールする。

$ sudo apt-get install ufw

ufwの状態の確認

ufwが有効になっているかどうかは次のコマンドで確認することが出来る。

$ sudo ufw status

ufwが有効になっていない場合は次のように表示される。

$ sudo ufw status
状態: 非アクティブ

SSHとHTTPだけ許可する設定

まず最初にすべて拒否にする。この段階ではufwは有効になっていないので、実際に通信が遮断されるわけではない。

$ sudo ufw default deny

次にSSHを通す。

$ sudo ufw allow 22

HTTPも許可する。

$ sudo ufw allow 80

最後にufwを有効にする。有効にした時点で設定が有効になるので、設定が間違っていないか確認しよう。設定の確認はsudo ufw statusだ。

$ sudo ufw enable

これで外部に公開するポートを制限することが出来た。

Androidのビルドをする際に、環境設定として次のコマンドを実行する。

source build/envsetup.sh

しかし、Zsh上で実行すると次のエラーが出る。

build/envsetup.sh:1096: no matches found: vendor/*/vendorsetup.sh

これは次のコマンドを実行することで回避することができる。

unsetopt NOMATCH

Android3系の設定画面は、左にメニュー(これをヘッダーと呼ぶ)、右に設定内容というのが標準的になっている。
このヘッダー付き設定画面を作るには、PreferenceActivityを継承したクラスでonBuildHeadersをオーバーライドし、次のようなxmlをloadHeadersFromResourceで指定する。

<preference-headers xmlns:android="http://schemas.android.com/apk/res/android">
	<header
        android:fragment="FragmentClass"
        android:title="タイトル" android:summary="サマリー"/>
    <header
        android:title="サイトを開く"
        android:summary=""
        >
        <intent android:action="android.intent.action.VIEW"
                android:data="http://www.google.com" />
    </header>
</preference-headers>

で、設定画面内で画面遷移するには、FragmentManagerを使う。

FragmentManager fm = getFragmentManager();
FragmentTransaction transaction = fm.beginTransaction();
MyFragment fragment = new MyFragment();
transaction.replace(parentId, fragment);
transaction.addToBackStack(null);
transaction.commit();

FragmentをreplaceするIDはFragment.onCreateViewの第二引数で渡されるViewGroupのgetIdで取得した値を設定する。
画面遷移を戻る場合はFragmentManager#popBackStack()だ。

そして、場合によっては深い階層にある自作の設定画面に直接遷移したいことがある。
そういう場合は次のようにIntentを投げる。
setClassでPreferenceActivityを継承したクラス。putExtraのEXTRA_SHOW_FRAGMENTでFragmentのクラス名を指定するのがポイントだ。

Intent i = new Intent();
i.setClass(this,MyPreferenceActivity.class);
i.putExtra(PreferenceActivity.EXTRA_SHOW_FRAGMENT, "jp.rainbowdevil.MyPreferenceFragment");
i.putExtra("ID", 1);
startActivity(i);

表示した設定画面のFragment内でIntentの情報を受け取るには、getActivity().getIntent()を使おう。

また、開いた設定画面のFragmentのボタンを選択すると、設定画面のFragmentを遷移したい場合がある。その場合は次のようにして画面遷移を行う。

PreferenceActivity activity = (PreferenceActivity)getActivity();
MySettingPreference preference = new MySettingPreference();
activity.startPreferenceFragment(mySettingPreference, true);

Androidで、その端末にインストールされているアプリの一覧とともに、そのアプリのバージョンを取得したいことがある。
PackageManagerでアプリ一覧を取得し、getPackageInfoでさらにそのアプリの詳細を取得することができる。

List<ApplicationInfo> list = packageManager.getInstalledApplications(0);
        for (ApplicationInfo applicationInfo : list) {
			try {
				PackageInfo info = packageManager.getPackageInfo(applicationInfo.packageName, PackageManager.GET_META_DATA);
	            Log.i("PackageManagerTest", applicationInfo.packageName + ":"+info.versionName+":"+info.versionCode);
			} catch (NameNotFoundException e) {
				e.printStackTrace();
			}
        }

EmacsのOrgModeはメモや作業ログを残していくには最適のツールである。

そして、Evernoteはメモを保存するには最高である。しかし、Evernoteのクライアントは最悪でもある。
そこで、それぞれの最高の部分をあわせるため、EmacsからEvernoteの機能をしたい。そこで使うのが、emacs-evernote-modeである。

使用するのに必要なのは、ruby、w3mである。Windowsから利用する場合は、cygwinでインストールする。

今回はWindows7にGnupack7を使いEmacsとCygwin環境を作る。
Gnupackをダウンロードし、適当な場所に解凍する。

Rubyとw3mのインストール

evernote-modeにはRubyとw3mが必要なので、それらをインストールする。
gnupackには簡単にcygwinのモジュールをインストールすることができるcyg-pmと言うのがあるので、それを用いてインストールを行う。
mintty.exeを開くとGnupackのcygwin環境でターミナルが起動するので、cyg-pm install rubyとcyg-pm install w3mを実行し、インストールしよう。

次に、evernote-modeをダウンロードする。今回は0.4.1を用いた。それを次の場所にコピーする。
gnupack_basic-7.00\app\emacs\site-lisp

mintty.exeを起動し、/app/emacs/site-lisp/evernote-mode-0_41/rubyに移動する。
そしてruby setup.rbを実行する。

evernote-modeを使う設定として、gnupack_basic-7.00/home/.emacs.elに次の設定を追加する。

(add-to-list 'load-path "c:/Users/kitamura/Documents/gnupack_basic-7.02/app/emacs/site-lisp/evernote-mode-0_41")
(require 'evernote-mode)
(setq evernote-username "EvernoteのID") ; optional: you can use this username as default.
(setq evernote-enml-formatter-command '("w3m" "-dump" "-I" "UTF8" "-O" "UTF8")) ; option
(global-set-key "\C-cec" 'evernote-create-note)
(global-set-key "\C-ceo" 'evernote-open-note)
(global-set-key "\C-ces" 'evernote-search-notes)
(global-set-key "\C-ceS" 'evernote-do-saved-search)
(global-set-key "\C-cew" 'evernote-write-note)
(global-set-key "\C-cep" 'evernote-post-region)
(global-set-key "\C-ceb" 'evernote-browser)

これでEmacsからEvernoteを使うことができる。

 

編集中の変更をキャンセルし、最後にコミットされた状態に戻したいことがある。gitコマンドでやるにはgit checkoutだが、EGitではcheckoutと言う項目が無い。

EGitでそれをどうするかというと、プロジェクトを右クリックし、[Team]-[Reset]を選択しよう。
Resetダイアログが開くので、ReferencesのHEADを選ぶと最後にコミットされた状態に戻すことができる。
Reset TypeをHardとすることで全部戻るようだ。(他にSoft、Mixedがあるが詳しい違いは未調査)

Eclipse Indigo(3.7)から、EGit1.0がデフォルトで付属されるようになり、gitを使う機会が多くなりそうだ。
今まではSubversionを使っていたけれど、個人用のリポジトリもgitに移行していく。
さくらのVPSで稼働しているUbuntu上にリポジトリを作成する。
さくらのVPSは秘密鍵付きのSSHでログインしているので、それでgitにもアクセスする。

gitリポジトリの作成

最初に、サーバ側でリポジトリを作成する。適当なディレクトリでgit init –bare –shared=trueを実行すればOKだ。

EclipseのSSH設定

次に、EclipseでSSHのキーを登録する。PreferencesのSSH2のページを開こう。

Key ManagementのLoad Existing Keyを選択し、既存のキーを選択する。もちろん既存のキーがなければ生成する。生成したキーを用いてSSHでログインする方法は省略。
ロードしたらSave Private Keyで保存する。
単にキーをEclipseから見えるsshディレクトリにコピーすれば良いだけかもしれない。

Eclipseでgitリポジトリのクローン

次に、サーバ上に作ったgitリポジトリをローカルにクローンする。Git Repositoriesビューを開き、ビューの上のボタンから、Clone Git Repositoryを選択する。

リポジトリのURIを入力する。サーバのアドレスとリポジトリのパスを入力する。
サーバがrainbowdevil.jpで、リポジトリのパスが/home/hoge/repoであるならURIは次のようになる。
ssh://rainbowdevil.jp/home/hoge/repo
URIを入力すると、HostとRepository pathが自動で設定される。

ユーザ名も指定し、Nextボタンを選択すればOK。

Eclipseへのインポート

あとはcloneしてきたリポジトリを右クリックし、Import Projectを選択してEclipseのプロジェクトとしてインポートしよう。

SSHがつながらない場合

cygwinでさくらのVPSサーバに接続できているので、EclipseでもcygwinのSSHを使いたい。
しかし、puttyがインストールされていると、puttyのsshを使ってしまい、鍵が合わないなどの問題があった。あと、TortoiseGitを入れていると、TortoiseGitに付属のputtyを使ってしまったりと問題があった。
使うssh.exeの直接指定ってどこでできるんだろう。

携帯向けのAndroidアプリをAndroid3.0のタブレットで動作させると、NetworkOnMainThreadExceptionが発生している箇所があった。
どうもAndroid3.0からメインスレッド(UIスレッド)から通信を行うとNetworkOnMainThreadExceptionが発生するようになったようだ。

まぁ通信に問題があると一発でApplication Not Respondingになるから、それを予防するために当然の対応ともいえる。
詳しくはこちら
Application Not RespondingにさせないためのはDesigning for Responsivenessを参照。

© 2012 RainbowDevilsLand Suffusion theme by Sayontan Sinha