2013年3月16日

Cocoa Emacs 24.3 構築 (2013/03版)

暫く使っている Cocoa Emacs を更新していなかったので、24.3 に上げてみた。

当てるパッチは inline patch とポップアップフリーズ対応パッチくらい。

24.3 には既にフルスクリーン実装が入っているので、よく使われているフルスクリーンパッチは外した。

普通に安定してる。。。良い事。

但し、フルスクリーン時に、ツールバー表示をトグルすると上下に変な隙間が出て、変だ。

どうしたもんだかなぁ

不具合の報告は既にあり(1)、trunkでは既に解消済みらしい。

イマイチ trunk を常用する気はないので、闇雲に探すと、このコミットがどうやら該当の修正らしい。

適当に cherry-pick し衝突を修正して、24.3 用の適当なパッチを使って、構築すると、確かに変な挙動は修正されている。

良き事かなぁ


[全文を読む]

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

参考


[全文を読む]