開発中に気付いた事 2010/12/18 追記あり 2010/12/19 公式の方(@masuidrive氏)に口頭で説明、概ね本社に報告していただける方向に 2010/12/21 追記あり 2010/12/21 追記あり(おまけ部分を改定) 2010/01/06 追記あり(Ti.platform が null になる件) 2010/02/03 追記あり(ビルド時DB更新エラーの回避方法)(フルビルドでandroidフォルダは残すよう明記) ・ビルド関連 Titanium Mobile android win32 1.4.X〜1.5.1 おそらく iOS Mac では発生しないことが多いかと 問題その1:Copying project resources.. まででLaunchが中断する 日本語フォルダ名・ファイル名を使うと発生 一度発生するとプロジェクトフォルダを移動しても解決しない Python の sqlite3 モジュールが、登録更新時は素通しし、検索時のみ unicode 化するため 元のエンコーディングが Windows-31J だったという情報を持たないため変換エラーで落ちる infoレベルで次の行 forcing full re-build.. が出ていればこの処理は過ぎている traceレベルでも次行以降に何も出ていなければこの状態の可能性が高い 問題その1対策その1 日本語フォルダ名・ファイル名は決して使用しない 間違っても使用しない うっかり同一フォルダ内コピーで「コピー〜」ができたら Launch する前にとにかく即行でリネームする 問題その1対策その2 既に使用してしまった場合、かつSDKを書き換えたくない場合 sqlite3 のデータファイルを削除する Titanium の関連フォルダは以下の通り プロジェクトワークスペース:ユーザが決める プログラムファイル:\Program Files\Titanium Developer\ (主に HTML/JS) SDK本体、同梱プログラムなど:  XP:\Documents and Settings\All Users\Application Data\Titanium\  Vista/7:\ProgramData\Titanium\ (以下 TI_HOME と表記) mobile SDK本体:(TI_HOME)\mobilesdk\win32\1.5.0\ (主に Python) デベロッパのデータ:  XP:\Documents and Settings\(ユーザ名)\Application Data\Titanium\  Vista/7:\Users\(ユーザ名)\AppData\Roaming\Titanium\ この他に android SDK(や eclipse を併用しているならそれも)のフォルダもある 肝心の sqlite3 のデータファイルは残念ながら上のどこにもない ビルド時の sqlite3 のデータファイル:  XP:\Documents and Settings\(ユーザ名)\.deltafy\deltas  Vista/7:\Users\(ユーザ名)\.deltafy\deltas 分割管理も結構だがもう少し場所をまとめられないものか このファイルの削除の際は、デベロッパを終了してから削除する (削除と書いてあっても初回はリネームにして戻せるようにしておくのは当然の自衛) 誤って起動したまま削除した場合、Launch して Trace レベルのログが データベースオープンエラーで停止したのを確認後、再度 Launch する 削除後は当然全てのプロジェクトがフルビルド状態になる 但しフルビルドを行いたい場合には上記ファイルではなく 2011/02/03 訂正ここから プロジェクトフォルダ\build\android\ の下を全て削除するほうが適切(削除と書いてあっても以下同文) android\ フォルダそのものは残しておかないと別の問題が発生する (ログ表示エリア、Launchボタンなどが表示されなくなる) 2010/02/03 訂正ここまで 問題その1対策その3 日本語フォルダ名・ファイル名を使用しても大丈夫なようにSDKを書き換えたい場合 (TI_HOME)\mobilesdk\win32\1.5.0\android\deltafy.py の(フォルダ名はその2を参照)の84行目付近 self.conn = sqlite3.connect(self.db_path, detect_types=sqlite3.PARSE_DECLTYPES) self.conn.execute('create table if not exists timestamps (path text, modified timestamp)') ↓ self.conn = sqlite3.connect(self.db_path, detect_types=sqlite3.PARSE_DECLTYPES) self.conn.text_factory = str self.conn.execute('create table if not exists timestamps (path text, modified timestamp)') に変更すると、検索時にユニコード変換しなくなる Python なので上下と字下げを一致させるように注意 登録更新・参照とも素通しなので問題はないと思われる 但し標準配布状態とデータ型が変わるので書き換えは自己責任で (ビルド時のファイル名比較用なので生成ファイルに影響はないはず) 問題その1対策その4 既に異常終了したのか時間がかかる処理中か区別するためにSDKを書き換えたい場合 (TI_HOME)\mobilesdk\win32\1.5.0\android\builder.py (2010/12/18 ファイル名誤り修正) の1474行目付近、 if __name__ == "__main__": の次の行から最終行(1574行付近)までを以下のように囲む if __name__ == "__main__": try: print "[WARN] %s %s %s start." % (os.path.basename(sys.argv[0]), sys.argv[1], dequote(sys.argv[2])) … sys.exit(0) finally: print "[WARN] %s %s %s exit." % (os.path.basename(sys.argv[0]), sys.argv[1], dequote(sys.argv[2])) Python なので上下との字下げの関係に注意 try: finally: は空白2個で字下げを浅くしてある 色で区別しやすいように敢えて警告レベルにしてある Launch すると引数を変えて2回呼ばれ、2回目の呼び出し前に数秒の待機があるので注意 2010/12/18 追記ここから 上記は 1.4.X での経験則で、1.5.X では様子が変わっている 更新処理(insert、update)時にDBファイルオープンエラーで落ちることが多発 現象としては、sqlite3 のDBファイルのあるディレクトリにも書き込み権限を与えないと、 更新処理時の一時ファイル作成でエラーになるという有名な問題と同種に見える 但し、このケースでは、ディレクトリもそのスクリプトで作成していること、 デバッグ出力を足して確認すると Launch 後最初の更新ではないこと、 他に何も対処せず数回 Launch を繰り返すと通ることから権限の問題である可能性は低い (しかし検索しても権限問題が多くてそれ以外の原因の情報が見つけられていない) 現状、対策としては、数回 Launch を繰り返すことしか思い付けていない(繰り返せば通る) そもそもこのDB管理は本当に必須の処理なのか? ディレクトリ内のファイル自体の有無と更新日時の比較では問題があるのか? コピー、コンパイル、コンバートなどより管理用DBアクセスのほうが重そうな気もするが 2010/12/18 追記ここまで 2011/02/03 追記ここから android 上のファイルの更新日時が(adb shell ls で)分単位までしか取れないため、 更新時間差1分以内の更新ファイルを検出するためにDB管理が使われているのかもしれない 実際、このサイトで配布している sync,cmd は、時間差1分以内の更新を同期できていない しかしDB管理して転送ファイルを絞るよりも、毎回全転送するほうが短時間かもしれない 上記問題は、現状 deltafy.py 内の全ての更新処理で sqlite3.OperationalError を except し、1秒 sleep してリトライする修正で、解決ではないが概ね回避はできている self.conn.execute('insert into timestamps(path, modified) values (?, ?)', (path, timestamp)) self.conn.commit() ↓ try: self.conn.execute('insert into timestamps(path, modified) values (?, ?)', (path, timestamp)) self.conn.commit() except sqlite3.OperationalError, msg: print '[WARN] sqlite3.insert [' + path + ']' + str(msg) time.sleep(1) self.conn.execute('insert into timestamps(path, modified) values (?, ?)', (path, timestamp)) self.conn.commit() のような修正を insert update delete を含む SQL 全てに対して行う 2011/02/03 追記ここまで 問題その2:js 内に utf-8 が含まれるとコンパイルエラーになる 筆者の環境では一度この問題が発生し、エラー出力も確認し、 以下の方法で解決したが、その後元に戻してもエラーが発生しなくなった このため、現にエラーが発生している状況以外では適用する必要はなく ビルド成功後、元に戻してみて再発しなければそのままにすることを推奨する 問題その2対策その0 1.5.0 では適切に改善されたためそれ以降ではこの対策は不要 1.4.X ではそもそもエラー出力が複数行だと内容が表示されなかったため、確認するには (TI_HOME)\mobilesdk\win32\1.4.*\android\run.py 28行目付近 #sys.stderr.write("[ERROR] %s %s" % (args[0],str(se))) ↓ sys.stderr.write("[ERROR] %s\n" % args[0]) for line in str(se).splitlines(): if line: sys.stderr.write("[ERROR] %s\n" % line) Python字下げ以下同文 問題その2対策その1 (TI_HOME)\mobilesdk\win32\1.5.0\android\compiler.py 145行目付近 jsc_args = [self.java, '-classpath', js_jar, 'org.mozilla.javascript.tools.jsc.Main', ↓ jsc_args = [self.java, '-Dfile.encoding=UTF-8', '-classpath', js_jar, 'org.mozilla.javascript.tools.jsc.Main', Python字下げ以下同文 ・JSS関連 Launch 時に プロジェクトフォルダ\build\android\gen\(パッケージパス)\ApplicationStylesheet.java に Java ソースとして生成されコンパイルされている ソースを見ればjssファイルとしての解釈結果は確認できる 但しこの結果をクリエイト時にマッチングするアルゴリズムに問題あり Ti.include() 呼び出し以降では機能しない 例えば KitchenSink の app.js で 321 行目付近の Ti.include("examples/version.js"); を先頭行に移動させるだけで発生する (currentWindow の url ではなく)Context の currentURL で紐付けているため Java の evalFile() 内で currentURL を変更して復帰時に戻していないためか? CommonJS 仕様の require() を使えば問題は発生しない (関数スコープで囲む必要があるため evalFile() を使っていない) とはいえ全てのインクルードファイルがモジュール的であるとも思われない 現状、パスを含まないベースネームのみで画面キーとしている 別フォルダに同名の画面用jsファイルがあると衝突する (KitchenSink の label_basic.jss が上位にあるのもこのためか?) そもそも紐付けをユーザが指定できないのが問題では? Ti.UI.createWindow({url:'/sub.js', jss:'/sub.jss'}); あるいは Ti.UI.createWindow({url:'/sub/sub_1.js', jss:'/sub/sub.jss'}); Ti.UI.createWindow({url:'/sub/sub_2.js', jss:'/sub/sub.jss'}); Ti.UI.createWindow({url:'/sub/sub_3.js', jss:'/sub/sub.jss'}); のように Window.url と同タイミングでの指定ができれば アプリ全体だけではなく関連画面グループでの共有も可能となる 少なくとも currentURL の Ti.include からの復帰対応か 紐付け元の currentWindow.url への変更は必須ではないかと background-color / backgroundColor の値の解釈がおかしい ウィンドウで発生、ビューやラベルでは問題なさそう background-url が backgroundImage になる text-align / textAlign は両方通る z-index は通らないが zIndex は通る font-size は通るが fontSize は通らない font 系以外のオブジェクト値プロパティは常に通らない csscompiler.py で、 一部はマッピングで別名を追加、元項目も残る、 一部はこのマッピングに登録漏れ、 font 系は特別処理でオブジェクト化、 他のオブジェクトプロパティは対処なし、 のため、このような挙動になる background-url はマッピングの登録誤り かつての Netscape の jss のようなものを想像したがそういうものではなさそう jss と名付けつつ実態はほぼ css そのもの css パーサを通す設計のため、値に JSON をそのまま記述すると落ちる #label1 {color:#fff; font:{fontSize:20, fontWeight:"bold"};} /* パースエラー CSS構文違反 */ 代案としては、url() などと同様、 #label1 {color:#fff; font:js({fontSize:20, fontWeight:"bold"});} あるいは、擬似要素 ::value などと同様、 #label1 {color:#fff;} #label1::font {fontSize:20; fontWeight:bold;} とすれば、とりあえずCSSパーサまでは通るはず 後者ならその後 def transform_fonts(self,dict): for key in dict: for sel in dict[key]: props = sel.split(':') if len(props) == 1: continue d = dict[key] for i in range(len(props)) if props[i] not in d: d[props[i]] = {} d = d[props[i]] d.update(dict[key][sel]) return dict 辺りで3重以上の入れ子にも対応できそうだが backgroundGradient のようにマップとリストが混在すると無理か 前者は CSS と JSON の構文が、異なるもののかなり似ているのが問題 区切りの ';' と ',' の違い、キーワードの "" の有無など、混同の元 3項演算子で iOS 用と android 用の振り分け対応ができるなど表現力は高い SDK同梱のPythonが何故か2.5止まりなので(配布サイズがコンパクトとかで?) 2.6から標準になったJSONモジュールでのサンプルコードは書いていない (どうやら Mac にプリインストールされるバージョンに合わせているらしい?) TUB の立場から見ると、スタイルシートはCSS互換のほうが望ましい面もあり 非互換だとウェブブラウザによるXMLの直接表示確認の障害になり得るため css で display:block; position:absolute; などいろいろ追加して 拡張子を .html に変えればある程度は確認可能になるか? とはいえ実際にはHTML(か、いっそXULにでも?)コンバートしないと無理か? iOS の XIB や android のレイアウトXMLとの相互変換を考えるべきか? この辺りは XSLT などに強い方にご協力いただけると いずれにせよ何でもありのjssよりはcss準拠のほうがこういう話向き 但しハイフン区切りとキャメルケースの非対称性は解消してもらいたい z-index などは漏れなくマッピングに拾い、 fontSize なども transform_fonts() で拾わないと混乱の元 ・多言語関連 手作業で プロジェクトフォルダ\i18n\(ロケール)\strings.xml を編集しておく Launch 時に プロジェクトフォルダ\build\android\res\values-(ロケール) プロジェクトフォルダ\build\iphone\build\values-(ロケール) にコピーされている en(又は en-us)が values となり未対応ロケール時に使用されるようだ AlertDialog.titleid や Notification.messageid など未実装の場合、 (title|message) などに Ti.Locale.getString(キー, 代替値) を設定する 代替値はキーから翻訳値が取れない場合に使用されるようだ Ti.Locale.getString() は短縮形 L() でも代用できる AlertDialog.message が AlertDialog.messageid の 代替値として機能すればよいのだがそうはなっていないようだ 従って代替値が必要な場合は messageid があっても無視して message:L() を使用することになるようだ 標準で短縮形が設定されていることから 開発元でもむしろ後者の多用も想定しているのではないか? あるいはキーとして英語又は開発者の母国語での翻訳値を使用し、 (該当言語の string.xml はキーと値が原則一致する) 翻訳値が取れない場合はキー自体が代替値として返されるとよい (GetTextにはその種のオプションがなかったか?) TUB で、現行の などと変更として、 {ui:"Label" params:{text:Ti.Locale.getString("日本語","日本語")}} と i18n/ja/strings.xml 日本語 i18n/en/strings.xml Japanese を自動生成できるようになるとよいか? Ti.Locale.setString(ロケール, キー, 翻訳値) などがあればリソースの自動生成まではしなくてよいのだが ・プラグイン関連 プラグインの追加場所 全体共有 (TI_HOME)\plugins\プラグイン名\プラグインバージョン\plugin.py プロジェクト単位 プロジェクトフォルダ\plugins\プラグイン名\plugin.py プラグインの設定 プロジェクトフォルダ\tiapp.xml プラグイン名 ・その他 1.5.0 でプロジェクト新規作成直後の状態で Ti.Platform がセットされてこないことがあった ある程度作業を進めて以降は発生しなくなった 2010/12/18 追記ここから 1.5.X になって、○○が iOS / android で動かなくなった、という情報をネットでみかける Ti.Platform が null であれば機種チェックで落ちるので原因の1つとして疑わしい ちなみに確認時は app.js 先頭行から Ti.API.info(Ti.API); Ti.API.info(Ti.UI); Ti.API.info(Ti.Platform); として、3つ目だけ null になっていた 2010/12/18 追記ここまで 2011/01/06 追記ここから http://developer.appcelerator.com/question/87461/continuous-150-on-android--tiplatformname-crash tiapp.xml をタッチ(再保存などで更新日時を新しく)してビルドすればよい? 2011/01/06 追記ここまで TabGroup.setActiveTab() TabGroup.open() の順に実行した場合、TabGroup のポストオープン処理内で Tab→Windowのオープンが2回呼び出される Javaソース内でタブを順次登録後にアクティブタブに変更しているため、 1つ目のタブ登録時とアクティブタブ変更時に呼ばれているものか? アクティブタブに1つ目のタブを指定した場合、 TabGroupへの登録時のオープン処理が終わる前に アクティブタブ変更処理が呼ばれ、 クローズ状態とみなされて再度オープン処理が呼ばれるものかと 結果、同一画面に同一画面要素が2つずつ貼られていると推測している アクティブタブに2つ目以降のタブを指定した場合、 同様に2つのタブのオープン処理が呼ばれるが、 1つ目のタブのウィンドウのjsの1行目時点で 既に currentTab、currentWindow がアクティブタブ側に切り替わっている 結果、アクティブタブの画面に両方の画面要素が貼られてしまう 1つ目のタブのウィンドウのjsでインクルードするjsが大きいほど発生頻度増 以上は重いことで名高い android SDK のエミュレータ上での発生、 実機は速いのでアクティブタブ変更までに1つ目のオープン完了が間に合うのか? 2010/12/18 追記ここから 問題 Timed out waiting for emulator to be ready, you may need to close the emulator and try again 対策 このメッセージのときは Launch だけを繰り返しても回復しない emulator が開いている場合、閉じてから再度 Launch emulator が開いていないのにこのメッセージが出る場合、コンソールから adb kill-server してから再度 Launch、数回繰り返さないと回復しないこともある 問題 No such file or directory: '(ユーザホーム)\\.android\\avd\\titanium_loading..._loading....avd\\config.ini' 起動直後、SDK と Screen のメニュー項目読み込みが終わる前に Launch を押すと発生する 対策 落ち着いてメニュー項目の表示内容が表示されてから Launch を押す システム側で、メニュー選択値が正しく読めない間はJSからPythonを呼ばないようにすべき 問題 jssの総量が大きくなるとアプリ起動時に異常終了又は無反応になる ビルド時の生成ソース プロジェクトフォルダ\build\android\gen\jp\locker\kitchenwork\ApplicationStylesheet.java のサイズで350〜400KB辺りがデッドラインか? そこから100KB分程度jssファイルを削除すると正常動作する 削除するjssを入れ替えても結果は同様 同梱の Pages.jss1 はこの問題が発生するソース 同じく Pages.jss2 はこの問題の回避のため global.jss に集約したソース 同じく Pages は Pages.jss2 でも値が反映されないため独自の仕組みに変えたソース 問題 android SDK 純正エミュレータが重い 高負荷で正常なアプリやビルド処理が異常動作するレベルで重い 対策 仮想環境上で android-x86 を動作させて代用する Java開発で eclipse などから同じことをさせる方法はネット上で複数確認できる 但し、 android-x86 インストール ネットワークのブリッジ設定 adb からの認識 で、それぞれサイトを探す必要はあるかもしれない ここでは Titanium Mobile SDK の修正方法のみ示す (TI_HOME)\mobilesdk\win32\1.5.1\android\builder.py 331行目付近 if device.is_emulator() and device.get_port() == 5560: info("Emulator is running.") sys.exit(0) ↓ if device.is_emulator() and device.get_port() == 5560: info("Emulator is running.") sys.exit(0) if device.is_emulator(): warn("Other emulator is running.") sys.exit(0) 又は if device.is_emulator(): info("Emulator is running.") sys.exit(0) Python字下げ以下同文 純正エミュレータを終了、 android-x86 を起動、 adb で認識させた状態で Launch 2010/12/18 追記ここまで 2010/12/21 追記ここから 上のエミュレータの件は、SDKの書き換え不要で android-x86 側のポートを Titanium Mobile にあわせる方法を記載 http://locker.jp/titanium/android-x86.html 問題 R.java の出力でエラーになる Application id がピリオドで区切られていないのが原因 Titanium ではなく android の制限 対策 Application id をピリオドで区切る jp.example.app myname.app など とてもどうでもよい問題 メッセージが逆 対策 (TI_HOME)\mobilesdk\win32\1.5.1\android\builder.py 1111行目付近 if self.install: self.wait_for_device('d') info("Installing application on emulator") cmd += ['-d'] else: self.wait_for_device('e') info("Installing application on device") cmd += ['-e'] ↓ if self.install: self.wait_for_device('d') info("Installing application on device") cmd += ['-d'] else: self.wait_for_device('e') info("Installing application on emulator") cmd += ['-e'] ほとんどのユーザには無関係な問題 builder.py run builder.py run-emulator で avd_id と avd_skin を指定する方法がない 対策1 (TI_HOME)\mobilesdk\win32\1.5.1\android\builder.py 1514行目付近 avd_id = dequote(sys.argv[4]) if sys.argv[4] else "7" 1524行目付近 avd_id = dequote(sys.argv[4]) if sys.argv[4] else "7" avd_skin = dequote(sys.argv[5]) if sys.argv[5] else "HVGA" 対策2 ちゃんと app-id を自分で調べて打ち込んで builder.py simulator builder.py emulator のほうを使えばいい 対策3 普通に Titanium Developer から Launch ボタンを使えばいい 2010/12/21 追記ここまで 2010/12/22 追記ここから おまけ launch.cmd (XP用)(Vista/7 は TI_HOME=%ALLUSERSPROFILE%\Titanium) ──────────────────────────────── @echo off set TI_HOME=%ALLUSERSPROFILE%\Application Data\Titanium set TI_MOB_SDK=%TI_HOME%\mobilesdk\win32\1.5.1 set PYTHON_HOME=%TI_HOME%\modules\win32\python\1.1.0 set ANDROID_HOME=C:\Apps\android set TI_PROJ_HOME=%1 if "%2"=="rebuild" rmdir /s /q "%TI_PROJ_HOME%\build\android" if not exist "%TI_PROJ_HOME%\build" mkdir "%TI_PROJ_HOME%\build" if not exist "%TI_PROJ_HOME%\build\android" mkdir "%TI_PROJ_HOME%\build\android" start "emulator log" "%PYTHON_HOME%\python.exe" "%TI_MOB_SDK%\android\builder.py" run-emulator "%TI_PROJ_HOME%" "%ANDROID_HOME%" "3" "WVGA854" start "build install and launch" build.cmd ──────────────────────────────── build.cmd ──────────────────────────────── @echo off "%PYTHON_HOME%\python.exe" "%TI_MOB_SDK%\android\builder.py" run "%TI_PROJ_HOME%" "%ANDROID_HOME%" "3" if errorlevel 1 pause exit ──────────────────────────────── コンソールから >launch (プロジェクトフォルダ絶対パス) でプロジェクトがビルド、インストール、起動される >launch (プロジェクトフォルダ絶対パス) rebuild でプロジェクトがフルビルド、インストール、起動される 又は %1 を(プロジェクトフォルダ絶対パス)に %2 を %1 に書き直して保存すれば >launch >launch rebuild のみで可能 末尾の "3" "WVGA854" は builder.py を前述のように書き換えないと無視される 初期値は "7" と "HVGA"、"3" は 1.6 のこと、google maps を使う APIs 1.6 は "4" コンソールは新たに2画面起動する エミュレータ用 下の x86.cmd などで android-x86 を認識させていればそれを利用するので自動クローズ 純正エミュレータが Titanium 対応 port で起動していればそれを利用するので自動クローズ どちらもなければ純正エミュレータを Titanium 対応 port で起動、そのまま残る コンソールかエミュレータを手動でクローズすると他方は自動でクローズ 2回目以降の launch では新しいほうが自動クローズして元のほうがそのまま残る ログレベルは左端に E/ W/ I/ D/ T/ 環境変数 ANDROID_LOG_TAGS でレベル制御できるか? ビルド用 エミュレータの認識を待った後、ビルド、インストール、起動して自動クローズ エラー発生時はキー入力を待ってクローズ ログレベルは左端に [ERROR] [INFO] など、レベル制御は難しそう? これ自体を Python などで書き直せばログレベルもログファイルに残すのも自由か ログが2種類に分かれることで、時間がかかる箇所の感覚が掴み易くなる エミュレータが起動、adb に認識されるまでビルド側が待機しているとか ビルドが終わってインストールが始まるまでエミュレータ側が待っているなど 例えば2回目以降の Launch を早くするアドバイスとして エミュレータを閉じずに再利用することがよく薦められているが、 2回目以降に限って、ビルド側が Install を表示して終了待ち、 エミュレータがビルド待ちから Install 時の表示を始めた辺り、 1回目と比べるとGCなどの表示間隔がかなり遅くなっている 毎回閉じるのとどちらが早いかはアプリのサイズにもよりそう アプリが大きいと、前回使ったメモリや一時ファイルの後始末が 起動&認識より長くかかる可能性が高くなるものかと x86.cmd ──────────────────────────────── @echo off set ADBHOST=%1 adb kill-server adb start-server ping %ADBHOST% -n 4 adb devices adb -s emulator-5554 shell setprop service.adb.tcp.port 5561 for /f "usebackq tokens=2" %%i in (`adb -s emulator-5554 shell "ps | grep /sbin/adbd$"`) do adb -s emulator-5554 shell kill %%i adb kill-server adb start-server ping %ADBHOST% -n 4 adb devices start "android-x86 log" adb logcat ──────────────────────────────── android-x86 がインストール、設定済みであること 純正エミュレータを終了、android-x86 を起動後、コンソールから >x86 (androidx_86のIP) で Titanium Mobile 対応のポートで adb に認識される 又は %1 を(androidx_86のIP)に書き直して保存すれば >x86 のみで可能 この状態で Launch ボタン又は launch.cmd で android-x86 が使われる >set ADBHOST= & adb kill-server で android-x86 を起動したままadbの認識だけを解除できる この状態で Launch ボタン又は launch.cmd で純正エミュレータが使われる adb devices の表示は android-x86 起動直後なら emulator-5554 から emulator-5560 に変化するはず 1度解除した後は emulator-5560 のまま、 ポートの変更は emulator-5554 指定なので2度目以降は何も起こらないはず ping は接続確認と同時に認識待ちのウェイトでもある 筆者の環境では初期値の -n 4 が最適だが環境に合わせて変更するとよい 特に上のほうの adb devices で List of devices attached が空なら増やすこと 逆に下のほうの ping と adb devices は表示確認が不要なら切ってもよい ping の表示確認が不要なら末尾に > nul を追加 ログレベル等は launch.cmd でのエミュレータ側と同様 android-x86 1.6 を入れている場合、2.1 以降のAPIは使用できない APIs 1.6 もおそらくそのままでは無理、1.6 を指定する launch.cmd では "3" にして、builder.py も対応するよう修正しておく 2010/12/22 追記ここまで