TitaniumでAndroidの画面の向きを固定する

TitaniumでAndroidアプリを作っていて画面の向きを固定にしたくなったのですが、通常Androidでは

activityタグの中で下記のように設定します。

android:screenOrientation="portrait"

ただTitaniumではTitaniumでは一つ一つのActivityを意識しないため、おそらく個別の設定はなさそうです。(もしかしたらあるかもしれませんが)

そこで以下のようにtiapp.xmlに書いてみました。

<android xmlns:android="http://schemas.android.com/apk/res/android">
	<application android:screenOrientation="portrait"/>
</android>

が、うまくいきません。。。(´・ω・`)ショボーン

調べてみると下記に同様の質問をしている人がいたので、
http://developer.appcelerator.com/question/105411/disable-android-landscape-mode

下記のように設定してようやく画面を縦向きに固定できました!

var win = Titanium.UI.createWindow({
    url: 'hoge.js',
    title:'ほげ',
    backgroundColor:'#000',
});

win.orientationModes = [  
    Titanium.UI.PORTRAIT
];

ただ、これでは全windowごとに設定する必要があります。
tiapp.xmlに一括で書いたり出来ないのでしょうか・・・

vimでneocomplcacheを使ってTTにHTMLのコード補完をする

Androidアプリ開発メモ」というブログのタイトルですが、サーバサイド開発の際はvimを使ってPerlPHPのコーディングをする事が多いので、たまにはvimの話を書いてみます。
今回はコーディングを快適にするためにneocomplcacheを入れてみましょう。


neocomplcachevimeclipseなどのIDEのようなコード補完を実現するプラグインです。
インストールは以下からzipをダウンロードして、.vimフォルダ以下に展開します。
https://github.com/Shougo/neocomplcache


次に.vimrcに以下のような設定をすると補完が効くようになります。

let g:neocomplcache_enable_at_startup = 1

neocomplcacheは機能が非常に多いためここでは全部の詳しい解説は出来ませんが、以下が参考になると思います。
http://vim-users.jp/tag/neocomplcache/


また、普段テンプレートエンジンはtt(template toolkit)を使用しているため、tt用の補完もしたいのですがデフォルトだと *.tt の拡張子がvimに認識されません。


そこで以下の記事を参考に $HOME/.vimの下にfiletype.vimというファイルを作成します。
snippetsEmu.vimを使っていて、補完が効かない人はfiletypeが原因かもしれない
これでttの補完候補が表示されるようになりました。


ただ、テンプレートを書く際はttのコードだけでなくhtmlのタグも書く事が多いのですが、このままではTTのファイルを編集している時にHTMLの補完が出来ません。


困ったな、、、と思ってたら解決策が見つかりました!

一般的に知られていないことだが、'filetype'は複数の値を設定できる。例えば:setfiletype
c.doxygenなどとピリオドで区切った名前の列によって複数の値を持たせることができる。個人的には、複数の値を持つ場合は「compound
filetype」、通常の値の場合は「simple filetype」と呼び分けている。

http://whileimautomaton.net/2008/09/07213145


上記を参考に、filetype.vim

 au! BufRead,BufNewFile *.tt     setfiletype tt

を以下のように変更

 au! BufRead,BufNewFile *.tt     setfiletype tt.html


これでTT内でHTMLの補完も出来るようになりました!

参考にさせていただいた記事の方々、ありがとうございました。


neocomplcacheはコードのスニペットも補完出来ますし、またスニペット自体を自分で追加出来たりと便利な機能が多いですね。
最初はスニペットの機能があることを知らなかったのでsnipMateなどを入れていましたが、使ってるうちにneocomplcacheだけで足りる事が分かって驚きました。

スニペットについてはCatalystなどの自分がよく使うフレームワーク用に作成して追加していきたいと思います。

AndroidでTitanium.Network.HTTPClientを使うとUAがセットされない

Titanium.Network.HTTPClientで嵌りました。

Yahoo!APIを使ってデータを取ってくる処理を書いていたのですが、iPhoneでは動くのにandroidで動かないという現象が発生しました。

onerrorでエラー内容を見ると「Bad Request」とのこと。

試しにはてなやATNDなどの他のAPIを利用してみると正常にレスポンスが返ってきました。
どうやらなんらかの理由でYahoo!のみBad Requestを返すようです。

TITANIUM BBS(JP UNOFFICIAL)でもらったアドバイスに従ってリクエスト先をローカルのCatalystに変更してヘッダーをダンプしてみると、下記のようにandroidの場合だけUser Agentを送信していないことが分かりました。

#Chrome
$VAR1 = bless( {
                 'accept-charset' => 'Shift_JIS,utf-8;q=0.7,*;q=0.3',
                 'user-agent' => 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_6; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.204 Safari/534.16',
                 'connection' => 'keep-alive',
                 'cache-control' => 'max-age=0',
                 'accept' => 'application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5',
                 'accept-language' => 'ja,en-US;q=0.8,en;q=0.6',
                 'accept-encoding' => 'gzip,deflate,sdch',
                 'host' => 'localhost'
               }, 'HTTP::Headers' );

#iOSシミュレータ
$VAR1 = bless( {
                 'user-agent' => 'Appcelerator Titanium/1.6.1 (iPhone Simulator/4.2; iPhone OS; en_US;)',
                 'connection' => 'keep-alive',
                 'accept-encoding' => 'gzip',
                 'x-requested-with' => 'XMLHttpRequest',
                 'host' => 'localhost'
               }, 'HTTP::Headers' );

#androidエミュレーター
$VAR1 = bless( {
                 'user-agent' => '',
                 'connection' => 'Keep-Alive',
                 'x-requested-with' => 'XMLHttpRequest',
                 'host' => 'localhost'
               }, 'HTTP::Headers' );

他にもandroidの場合だけセットされていない値がありましたが、一番怪しいと思われるUserAgentを下記のように自分でセットしてからリクエストを送信すると、ようやくYahoo!からもレスポンスが返ってきました!

xhr.open('GET',url);
xhr.setRequestHeader('User-Agent',Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420+ (KHTML, like Gecko) Version/3.0 Mobile/1A537a Safari/419.3');
xhr.send();

ちなみにUAの値は"hoge"とかでも大丈夫だったので、Yahoo!APIはUserAgentに値があるかどうかだけチェックしているようです。

BBSで質問した経緯は下記に。
AndroidでTitanium.Network.createHTTPClient.onloadなどが実行されない

Androidの場合だけTitanium.Network.HTTPClientがUserAgentなどのヘッダをセットしてくれないようです。Yahoo!に限らず、UAをチェックするサービスはたくさんあると思うので気を付けないといけないですね。

TwitterやBBSで返信いただいた@masuidriveさん、@24okさん、ありがとうございました!

titaniumでError generating R.java from manifestが発生する場合の対処法

titaniumのandroid
Error generating R.java from manifest
が発生する場合、「Edit」の「Application ID」を確認しましょう。
Application IDが「Hoge」のようになっていたら、「com.Hoge」のようにパッケージ形式で記述すると直ります。(直らない場合もあるかも)

Titanium.UI.iPhone' [undefined] is not an object が発生した場合の対処法

Androidに限定した話題じゃないのですが、最近はJavascriptiPhoneAndroidのアプリが開発出来るTitanium Mobileをいじってます。

gihyo.jpで「Titanium Mobileで作る! iPhone/Androidアプリ」が連載されているので、そのサンプルコードを参考にアプリを作っていると以下のようなエラーが出ました。

Titanium.UI.iPhone' [undefined] is not an object
APIとして存在しているはずなのにオブジェクトではないというエラーで呆然としたのですが、調べてみると

http://developer.appcelerator.com/question/72821/titaniumuiiphonetableviewstyle-undefined-is-not-an-object

に「build/iphone/」の中を削除したらよいと書いてあったのでプロジェクトフォルダのbuild/iphone/*を削除してリビルドしたら無事にエラーが無くなりました。

そういえばデブサミに参加したときに@masuidriveさんのTitaniumのセッションを聞いたのですが、動かなくなった時はbuildの中を一度削除してくださいと言っていたような気がします。

嵌ったらとりあえず試してみた方がよさそうですね。

スリープ状態をアプリから解除する

端末の電源ボタンを押す等してスリープ状態に入ったまま、バックグラウンドでプロセスを動かし、なんらかのタイミングでスリープ状態を解除してアプリをresumeしたい場合は
android.os.PowerManagerとandroid.app.KeyguardManagerを使用します。

PowerManagerのWakeLockを使用するとスリープ状態から復帰したり、電源の状態を変えることが出来ます。
http://developer.android.com/reference/android/os/PowerManager.html


スリープ状態から復帰して何らかの処理を行う場合、

  1. PowerManagerで電源を付ける(スクリーンの照明をつけるかどうかはnewWakeLockのフラグの値で制御する)
  2. KeyguardManagerでスクリーンロックを解除する

という流れになります。

private WakeLock wakelock;
private KeyguardLock keylock;

//中略

//スリープ状態から復帰する
wakelock = ((PowerManager) getSystemService(Context.POWER_SERVICE))
		.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK
				| PowerManager.ACQUIRE_CAUSES_WAKEUP
				| PowerManager.ON_AFTER_RELEASE, "disableLock");
wakelock.acquire();

//スクリーンロックを解除する
KeyguardManager keyguard = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
keylock = keyguard.newKeyguardLock("disableLock");
keylock.disableKeyguard();

/**
    処理
*/


PowerManager.WakeLockの操作はバッテリーの状態に影響を与えるので、使い終わったらリリースする処理を忘れないようにしましょう。

@Override
public void onPause() {
	super.onPause();

	wakelock.release();
	keylock.reenableKeyguard();
}

Androidあるある その1 ブレークポイントを設定してもデバッグ出来ない

Androidアプリ開発で分かっているのによくやってしまう失敗をネタにAndroidあるあるをメモ。

eclipseで下記のようにブレークポイントを設定してデバッグ実行しているのに処理がブレークポイントで止まってくれない・・・(´・ω・`)ショボーン


はい、AndroidManifest.xmlを見直しましょう。

Applicationタブの以下を確認。

android:debuggable="true"

を設定しないとデバッグ出来ません。

いつも忘れてしまう・・・