Webサイトのスマホ対応記事の続きになります。
私はスマホ対応の方法として”User-Agent”(ユーザエージェント、通称UA)によるロジック切り分けを行っていますが、そこでちょっとした問題が発生したのでメモ書き。
以前の記事は以下
過去記事:ウェブサイトのスマートフォン対応(マルチスクリーン対応)①
過去記事:[Java,Struts2]ウェブサイトのスマートフォン対応(マルチスクリーン対応)
問題というのは、iPadでアクセスしているのにスマホ用画面が表示されてしまうといった不具合です。
原因は、iPhone,iPad両方に対応しているアプリ[Twitter for iPhone]からWebサイトにアクセスされた際、UAに[Twitter for iPhone]が書き込まれている為、iPadからのアクセスもiPhone(スマホ)だと判定してしまっていたというものです。
問題のアクセスログの例(改行入れてます)
xxx.xxx.xxx.xxx [2013/12/xx xx:xx:xx.xxx] 200 xxxxx "GET / HTTP/1.1" [REF:http://t.co/xxxxxxxxxx] [UA:Mozilla/5.0 (iPad; CPU OS 7_0_4 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Mobile/11B554a Twitter for iPhone]
私のロジックだと上記UAでは、端末はiPadですが使用アプリが自動で付与しているiPhoneという単語に分岐ロジックが反応してしまい、スマホだと判断されてしまいます。
分岐ロジックを以下のように修正して対応しました。
package xxx.interceptor; import org.apache.struts2.ServletActionContext; import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.interceptor.AbstractInterceptor; import com.opensymphony.xwork2.interceptor.PreResultListener; /** * クライアント端末がスマートフォンの場合、アクションresult文字列の先頭に"S_"を付与するインターセプタークラス */ public class SmartphoneInterceptor extends AbstractInterceptor { private static final long serialVersionUID = 1L; /** * インターセプト */ @Override public String intercept(ActionInvocation invocation) throws Exception { //アクション実行後のインターセプト処理 invocation.addPreResultListener( new PreResultListener() { public void beforeResult(ActionInvocation actioninvocation, String resultCode) { // User-Agent取得 String ua = ServletActionContext.getRequest().getHeader("User-Agent"); // [iPhone][iPod][Android][Windows Phone][BlackBerry]が含まれている場合のみ、スマホ用JSPを呼び出すように対応する。 // ※iPhoneの場合は[iPad]が含まれていない場合のみ。 // ※Androidの場合は[Mobile]が含まれている場合のみ。 int iphone = -1; if(-1 == ua.indexOf("iPad")) iphone = ua.indexOf("iPhone"); int ipod = ua.indexOf("iPod"); int win = ua.indexOf("Windows Phone"); int bb = ua.indexOf("BlackBerry"); int android = ua.indexOf("Android"); if(-1 < android) { android = ua.indexOf("Mobile"); } if(-1 < iphone || -1 < ipod || -1 < win || -1 < bb || -1 < android) { // スマホは"S_"付与 actioninvocation.setResultCode("S_" + actioninvocation.getResultCode()); } } } ); //次のインターセプタ処理 String result_code = invocation.invoke(); return result_code; } }
これで、UAにiPadが設定されている場合はiPhoneの判定を行わないようになり修正完了です。