サーバとやり取りするWebviewのアプリを動かす時にとりあえずやったことです。
実際のアプリはこれです。
https://itunes.apple.com/jp/app/mamononosubako/id1156425959
https://play.google.com/store/apps/details?id=jp.ringil.mamonodev
例ではCSSやJSだけ保持してbody以下の全体を読み込んでいますが、実際のアプリではJSONだけリクエストして文章や数字だけ書き換えている箇所もあります。
子供の頃CGIゲームとか管理してた頃を思い出してふと作りたくなった感じのnoob(職業プログラマでもなんでもなくニート⇒中身個人事業の法人作ってみたの流れ)なんでcanvasとかは使ってないよ!
でも/app/assets/の中の画像とか音楽とかなんでもローカルのファイル呼び出せるし、HTMLはgzipで圧縮してHTTP2でやり取りしているので読み込み時間はほとんどないです。
iOSのWebviewは優秀なのでサクサク動きますがAndroidは端末のスペックが高くないとキツイのが難点...
####リモートのjavascriptからTitaniumの機能が呼び出せない問題の解決
ただローカルのファイルからajax使ってるだけです。
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="Content-Script-Type" content="text/javascript">
<meta http-equiv="Content-Style-Type" content="text/css">
<meta http-equiv="Cache-Control" content="no-cache">
<meta http-equiv="Pragma" content="no-cache">
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
<meta name="format-detection" content="telephone=no">
<link rel="stylesheet" href="index.css" type="text/css">
<script type="text/javascript" src="index.js"></script>
<script type="text/javascript" src="jquery.min.js"></script>
</head>
<body id="bodytag">
<div id="aj">
</div>
</body>
</html>
$(function(){
web_error = function(e){
// エラー時の処理
};
aj = function(e){
// グローバルな関数でないとTitanium本体からevalJSで叩けなかったような...
e.preventDefault;
$("*").off().blur();
var query = $(this).attr('data-url') || e;
Ti.App.fireEvent("webview_auth");
var authqr = '';
if(auth){
authqr = '&auth=' + auth;
}
var div_target = ' #aj';
$.ajaxSetup({
timeout: 9000,
async: true,
beforeSend:function(){
/* reset */
}
});
$('#bodytag').load("https://example.com/" + query + authqr + div_target, function(response, status, xhr) {
Ti.App.fireEvent('webview_loaded',{hidetab:$('#tab').attr('data-hide')});
// 読み込んだ後の処理。ここではHTMLに埋め込んだdata-hide属性をTitaniumに登録した関数に送り込んでネイティブのタブバーを隠すべきページかどうか判定しています
if (status == "error" || status == "timeout"){
web_error();
}
$('.aj').one("tap",aj);
// HTMLでajクラスが指定されている箇所をタップするとサーバに別画面を要求できます。tapイベントはTocca.jsを使用
// 他にもイベント登録したり画面遷移後の処理を書く
});
});
return false;
};
});
var authdata = Ti.Filesystem.getFile(
// ゲームキャラの認証情報
Ti.Filesystem.applicationDataDirectory + "ファイルの場所"
);
var pWidth = Ti.Platform.displayCaps.platformWidth;
var pHeight = Ti.Platform.displayCaps.platformHeight;
var aspect = (pHeight / pWidth) / (16 / 9);
$.webview.width = 100 * aspect + '%';
$.webview.url = "/index.html";
// $.webviewはAlloyで作成
$.webview.addEventListener('load', function(){
$.webview.evalJS("auth = '" + authdata + "'");
// こうすればIDとかパスワードとか入力させなくてもただ起動するだけで登録時に作成した認証情報をサーバサイドに毎回送れます。二度目以降はwebview_authから読み出し
// なお向こう側のJSでvar auth;とかやってると送れません
$.webview.evalJS("aj('?q=top')");
// 初回起動時に$.webview.urlで/app/assets/index.htmlが読み込まれた直後に/app/assets/index.jsのaj関数を叩いてサーバにトップのデータを要求しています
});
Ti.App.addEventListener('webview_auth', function(e) {
$.webview.evalJS("auth = '" + authdata + "'");
});
あとはサーバサイドで送られたクエリに合わせたHTMLを返しましょう。例では、
https://example.com/?q=top
を最初に表示していますし、ここで返ってくるHTMLの中に
<div class="aj" data-url="?q=next"></div>
とか入ってればそこを押すことで次の画面に飛べます。
<a>
とかでHTML全体をリモートのURLに要求しちゃうともうTitanium本体とやり取りできませんし、ページ内のJSをまた読み込んだりするので非効率+変数を保持できません。
この方法であれば、一度保存した変数をページ間で共有出来ます。
SSL+HTTP2で通信してるとローカルのHTMLからリモートの画像を読み出せませんが、
<img src="data:image/gif;base64,base64でエンコードした画像データ">
とかサーバから返せば読み込めます。