2011年11月6日

Ant を使って Android アプリを構築する

Eclipse を使って Android アプリのプロジェクトを作成すると build.xml が作られずに、 コマンドラインからの構築ができない。 ただ、ちょっと前の ADT の話なので定かでない。。。

Eclipse を使うと署名済みの apk パッケージまで作れるが、 GUIを使って一連の操作を毎回するのは面倒なので、 ant を使ったリリース方法を調べてみた。

build.xml の作成

ant 化対応は非常に簡単で、プロジェクトのトップディレクトリで次のコマンドを実行すれば良い。

% ${ANDROID_SDK}/tools/android update project --path .

この時点で「ant debug」を実行すると bin/${project名}-debug.apk にデバック用のアプリが作成できる。

ただ、SDK Tools r14 から若干ファイルの構成が変更されているので注意が必要である。

build.xml
ant用の構築ファイル
ant.properties (旧 build.properties)
ユーザが追加して使用するもの。普通はコッチに書く。
local.properties
構築マシン固有の情報。現在は SDKへのパスのみ? VCSへの登録は避けるべきファイル
project.properties (旧 default.properties)
ADTによって維持される情報。

パスワードの自動入力

プロパティ値として key.store/key.alias/key.store.password/key.alias.password を設定しておけば、あとは万事取り計らってくれるようである。ただ、パスワード情報を記載するので、VCSへの登録される可能性が高いant.properties への記述は避けるべきで、VCS には登録しない secure.properties を作成して、コイツを読み込むように build.xml を変更するべきかなぁ。。。

build.xml
...
    <property file="ant.properties" />
    <property file="secure.properties" /> <!-- ここ追加 -->
...
secure.properties
key.store=path-of-keystore
key.alias=alias
key.alias.password=password
key.store.password=password

これで、 「ant release」の実行で bin/${project名}-release.apk に署名済みのapkパッケージが作成される。

リリース apk パッケージのファイルのカスタマイズ

ここまで来ると、リリース apk パッケージのファイル名に自動的に構築日時とversionCodeを埋め込みたいのが、エンジニアの心情だと思う。

build.xml をよく読むと、一番最後の import 要素の上に、任意のターゲットを追加すると良さ気である。なので、 次の deploy ターゲットを追加してみた。

build.xml
...
    <target name="deploy" depends="release" description="deploy">
        <xpath input="AndroidManifest.xml"
               expression="/manifest/@android:versionCode"
               output="config.versionCode"
               default="release"
        />
        <tstamp>
            <format property="config.versionDate" pattern="yyyyMMdd" />
        </tstamp>
        <property name="out.deploy.file"
                  value="${out.absolute.dir}/${ant.project.name}-${config.versionDate}-${config.versionCode}.apk"
        />

        <copy file="${out.final.file}"
              tofile="${out.deploy.file}"
              overwrite="true"
        />
        <echo>Deploy Package: ${out.deploy.file}</echo>
    </target>
...

これで、 「ant deploy」の実行で bin/${project名}-YYYYYMMDD-V.apk に署名済みのapkパッケージが作成される。

ターゲット名はあまり良く無いかも。。。

まとめ

makeファイルでのスクリプト片をantのタスク等で作成しないといけないのでいまいち使い勝手がよくわからない。 が、スゲー便利なんだろうなぁ。。。ant

参照

2011年6月5日

Cocoa Emacs 23 構築 (2011/06版)

定期的にCocoa Emacs 23 を構築して使っていた。今日も定期作業とおもって、構築したらビルドが失敗してしまった。。。

どうしたもんだかなぁ

ググってみると、、、MLの「Re: Emacs with Cocoa/GNUstep」の内容の通りで、lisp.h の修正の影響で nsmenu.m のビルドが失敗したみたいで修正したよ。それで emacs-23 ブランチには lisp.h の修正のみしかマージされていないみたいで、、、、うまく行かなかったということらしい。

masterブランチで作ってれば問題無しなのか、、、まぁそのうち emacs-23 ブランチに修正が降ってくるのかなぁ。

それまでは、以下のように対処してみた。(ヘタレ git 使いだから bzr の人用の手順は分からん、、、)

% git clone git://repo.or.cz/emacs.git
% cd emacs
% git checkout emacs-23
% git cherry-pick -n 207421c0af4edf88943e270ad4bc83934cabcc04
...
# src/nsmenu.m の2箇所のコンフリクトを修正
#  1箇所目は、memcpy を使ってる奴を残す
#  2箇所目は、どっちでもいい
#
...
% patch -p 0 < favorite-patch-file
...
# で構築
% eval "$(PATH= /usr/libexec/path_helper -s)"  # PATHをクリーンにする
% ./configure --with-ns
% make bootstrap
% make install
% open nextstep/Emacs.app

なかなか、いい感じだぁ

2011年5月26日

MacOSX で Zen Touch 2 (Android2.2)を開発端末にしてみる

自分の携帯を Androidの開発端末として使うのは、日常生活でメールや連絡が来たりするときに結構困る場合がある。なので、3〜4インチ程度の安いAndroid 端末が無いかなと物色したら、Zen Touch 2 がよさげ。

、、、

静電式のものに慣れているので、感圧式タッチパネルが違和感ありまくり操作がし辛いこと。

実物を見ないで、購入したので自業自得だが、、、ついでに、Android Market 非対応のも、、、 余り Android 端末としてはお薦めできないなぁ。。。まぁ音楽プレーヤーですね。

今まで扱った Android 端末は、何もせずに MacOSX の Android 開発用の SDK で認識されたので、気に留めるなかったが、こいつは認識しない。。。

はて、どうしたもんだかなぁ

熟考の結果、下記の投稿記事と同じ対応をすれば、adb で認識して、開発に使えるようである。

サクっと、認識させてみた。

# Creative Zen Touch 2 のベンダーIDを追加
% echo "0x041e" >> ~/.android/adb_usb.ini

# adb を再起動
% ${ANDROID_SDK_DIR}/platform-tools/adb kill-server
% ${ANDROID_SDK_DIR}/platform-tools/adb start-server
* daemon not running. starting it now on port 5037 *
* daemon started successfully *

# adb でデバイスのリストを確認
% ${ANDROID_SDK_DIR}/platform-tools/adb devices
List of devices attached 
16XXXXXXXXXXXX 0    device

これは adb が自前でAndroid のベンダーIDのリストを持っていることなのかぁ。。。

開発機としては、スペックも低いし解像度も高くなく無いので、下手な実装を洗い出せるので良いのかも。

ふむ、静電式でマーケット対応の一番安い奴でも探すかなぁ。。。

追記 (2011/11/06)

だれかに何故 0x041e なのか答えないといけない気がしたので。。。

単純に dmesg の直近で出てくるログ行で判断するのが正解かなぁ。。。

% sudo dmesg
...
USBMSC Identifier (non-unique): XXXXXXXXXXX 0 0x41e 0x4166 0x225
...

あとは USBストレージモードにして、システムプロファイルを参照するのも正解かぁ。。。

2011年5月7日

iOS の View Controller の lifecycle の図

iOS の VIewController のライフサイクル図を書き起こしてみた。

開発ドキュメントから読み取ったのだが、理解不足なためか不正確な部分も無きにしもあらず。精進せねば。

UIViewController のサイクル

まぁ、いらないと思うがPDF版 @ Google Docsもアップ。

2011年4月23日

Android の Activity のlifecycleの図

Android の基本の Activity のライフサイクルの図が開発サイトに乗ってる。

これでも前後の文章で補完すれば分かるんだが、2〜3ヶ月後の自分はまた忘れてる可能性大なので、 ちょこっと弄ってみた。

Android Activity 遷移図

まぁ、いらないと思うがPDF版 @ google docs もアップ。

2011年3月4日

Google提供の python ライブラリで Google Reader API を使ってみた

Google のサービスと連携するには Google Data API を使う。Googleが公式にサポートしているので、とても安心して使える。RSS リーダーとしてよく使われている Google Reader 用のAPI も。。。は、まだ公式には無い。

まぁ、色々な人が解析しており、GoogleReaderAPIのページが、詳細にまとまっている。

なので、Google 提供の python ライブラリで、Google Reader API を叩いてみた

ただ、サンプルを書いたあとで、pyrfeed内にGoogleReader 用のライブラリが含まれていたのに気付いたので、そっちを使うのがいいのかも。

インストール

MacPorts を使っているので、さくっとインストール。

% sudo port install py27-gdata

そうでないならば、gdata-python-clientから最新版をインストールする。

Google Reader 用の下準備と認証

gdata-python-client には、Reader サービスの固有の API は無いので、ベースのモノを適当に設定する必要がある。

import gdata.service

config = { 'Email': 'foobar@gmail.com', 'Passwd': 'password' }

# Google Reader サービス設定
service = gdata.service.GDataService(account_type='GOOGLE',
                                     service='reader',
                                     server='www.google.com',
                                     source='MyReaderHoge')

# Google アカウント設定とログイン
service.ClientLogin(config['Email'],config['Passwd'])

# 認証トークン(SIDの値)
print service.GetClientLoginToken()

# 書き込み用のトークンの取得
token = service.Get('/reader/api/0/token',converter=lambda x:x)
print "token:", token

'api/0'以下のレスポンスが AtomPub 形式では無く、小細工が必要である。gdata-python-clientには、ちょうど隙間が開いてるようである。。。

未読件数を取得

'api/0/unread-count'を JSON 形式で取得する

query = gdata.service.Query(feed='/reader/api/0/unread-count',
                            params={'all':'true', 'output':'json'})
feed = json.loads(service.Get(query.ToUri(), converter=lambda x:x))
unreadcounts = feed['unreadcounts']

# 全体の未読数を一番前に移動しとく
for i, item in enumerate(unreadcounts):
    if re.match(r'^user/\d+/state/com.google/reading-list$',item['id']):
        unreadcounts.pop(i)
        unreadcounts.insert(0,item)
        break

# 全体の未読数
print int(unreadcounts[0]['count'] if len(unreadcounts) > 0 else 0)
#=> 1

# 未読があるラベルとその未読数
for item in unreadcounts:
    if not re.match(r'^user/\d+/label',item['id']): continue
    print "count:%(count)s id: %(id)s" % item

#=> count:1 id: user/16814486509924941024/label/android

すべてのラベルを取得

query = gdata.service.Query(feed='/reader/api/0/tag/list',
                            params={'all':'true', 'output':'json'})
feed = json.loads(service.Get(query.ToUri(), converter=lambda x:x))
tags = feed['tags']

for item in tags:
    tag = re.sub(r'^user/\d+/',r'',item['id'])
    print "tag: %s" % tag
#=> tag: state/com.google/starred
#=> tag: state/com.google/broadcast
#=> tag: label/android
#=> tag: label/misc
#=> tag: label/neta
#=> tag: state/com.blogger/blogger-following

ラベルを指定して取得

android 関連の記事を 5 件見てみるかいな。。。

query = gdata.service.Query(feed='/reader/atom/user/-/label/android',
                            params={'n': str(5)})
feed = service.Get(query.ToUri())
for entry in feed.entry:
    print "===="
    dom = xml.dom.minidom.parseString(entry.ToString())
    print dom.toprettyxml(indent="  ")
    print "===="
    print "href: %s" % entry.GetHtmlLink().href
    print "title: %s" % entry.title.text
    # print "%s" % entry.summary.text

未読を既読に変更

先の記事は、読んだから既読にする。

# token, feed は、上に記載の書き込み用トークンと直前で取得した記事リスト
for entry in feed.entry:
    i = entry.id.text
    s = entry.source.extension_attributes['{http://www.google.com/schemas/reader/atom/}stream-id']
    ret = service.Post(urllib.urlencode({'i':i,
                                         'a':'user/-/state/com.google/read',
                                         's':s,
                                         'T':token,
                                         }),
                       '/reader/api/0/edit-tag',
                       converter=lambda x:x,
                       extra_headers={'Content-Type': 'application/x-www-form-urlencoded'})
    print i,ret

何でも無いが、この部分には半日悩んでしまった。

何気ない POST パラメータを送信する POST 処理なのだが、gdata.service.Postaplication/atom+xml形式のデータ送信を想定するため、明示的に Content-Typeを指定する必要がある!気づくまで、「400 Bad Request」+「X-Reader-Google-Bad-Token: true」に悩まされてしまった。

新しいフィードを登録

sub = r'feed/http://headlines.yahoo.co.jp/rss/rps_dom.xml'
ret = service.Post(urllib.urlencode({'s':sub,
                                     'ac': 'subscribe',
                                     'T':token,
                                     }),
                   '/reader/api/0/subscription/edit',
                   converter=lambda x:x,
                   extra_headers={'Content-Type': 'application/x-www-form-urlencoded'})
print sub,'subscribe',ret

購読しているフィードを解除

sub = r'feed/http://headlines.yahoo.co.jp/rss/rps_dom.xml'
ret = service.Post(urllib.urlencode({'s':sub,
                                     'ac': 'unsubscribe',
                                     'T':token,
                                     }),
                   '/reader/api/0/subscription/edit',
                   converter=lambda x:x,
                   extra_headers={'Content-Type': 'application/x-www-form-urlencoded'})
print sub,'unsubscribe',ret

参考

2011年2月15日

polipo + MacOSX で使う

普通の PC にインストールした Linux サーバに Squid + Squidguard で使っていたんだが、 別サーバを必ず立ち上げていないと行けないのが面倒なので、、、 乗り遅れ感が否めないが、polipo を常用をする環境を整えてみた。

移行に関しては、GUIは必要ないが launchd との繋ぎの設定ファイルを準備するのが面倒なので MacPorts パッケージを使いつつ、自前に用意したバイナリを使った。

本家サイトで公開されている git レポジトリを元に数点修正したものを使った。

  • 64 bit 環境だと stdarg 絡みで落ちるっぽい部分?を修正
  • redirector の入出力の行仕様をpolipo側でダミーで合わせた
  • censorReferer を maybe に設定した時、サブドメインに加えて指定のサイトリストも Referer を通す機能を追加

修正した履歴はgithubに公開してある。

最後の機能は、画像用を公開してるドメインが短縮した別ドメインに置き Referer で制限しているサイトに対応するためで、設定値uncensorRefererFileに、forbiddenと同じ形式で書けば、Referer を削除せずにスルーしてくれる。

まぁ、polipo も使えない事はないかなぁ。。。あとは、forbidden/redirector で Location を返す挙動がなんとかなれば、いいのになぁ。。。もうちょっと弄ってみるかなぁ

2011年1月27日

Mail.app の備忘録から Evernote に移行する

発売日に予約した IS03 が漸く入荷したので受け取ってきた。

いじり倒せる Android 端末が入手できた。 事前に電池のもちが異様に悪いと噂があったので、Killerアプリ等でコマメにアプリを終了し倒すように気を付けているので、ある程度許せる範囲に留まっている気がする。

まぁ、ノートパソコンにあるような大容量バッテリとかが出てくるのは、歓迎するが。。。どうなんだろう。

MacOSX の Mail.app には備忘録の機能が付いており、iOSとの組み合わせで同期が可能である。 結構便利でサクサク使っていたが、新規に Android でも同じようなことがしたくなって調べてみると、 どうも Evernoteが良いらしい。

メモに特化したアプリ、各プラットフォームにアプリがあり、相互に連携できる。。。なんか世の中凄いことになってるんだなぁ。。。

Mail.app の備忘録に蓄積したメモ書きを EverNote にサクっと移行するには、、、

どうすれば良いのだろうか?

何のことはない AppleScript を使うのが定石らしい。

参考URLの先コードを 「ユーティリティ」>「AppleScriptエディタ」にコピペして、「mailbox "Notes"」に書き換えて、実行すれば、「Imported Notes」という名前のノートブックの中にほぼ全部(「このMac内」の奴)コピー出来た。

あとは、ちまちまタグ付けや整理すればまた使いやすくなるのかなぁ。。。

参考URL

Cocoa Emacs 24.3 構築 (2013/03版)

暫く使っている Cocoa Emacs を更新していなかったので、24.3 に上げてみた。 当てるパッチは inline patch と ポップアップフリーズ対応パッチ くらい。 24.3 には既にフルスクリーン実装が入っているので、よく使われているフルスクリーンパッチは外し...