スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

WebViewの背景を透明にする方法。

WebViewのページが表示されるまで、白色の背景が表示されるのを防げる。

-----
webView.setBackgroundColor(0);
-----
スポンサーサイト

scrollbarを消す。

標準のブラウザみたいにスクロールをしている時以外は、縦スクロールバーを非表示にする方法。
API Level5となっているので1.6では利用できない。

public void setScrollbarFadingEnabled (boolean fadeScrollbars)

http://developer.android.com/reference/android/view/View.html#setScrollbarFadingEnabled%28boolean%29

他のにもxmlでの指定やフェードアウトの間隔等も指定できる模様。

TomcatのセッションIDのクッキー名の変更

以下の2つのプロパティで変更できる。

org.apache.catalina.SESSION_COOKIE_NAME - クッキー名
org.apache.catalina.SESSION_PARAMETER_NAME - URL書き換えのパラメータ名

以下は、Tomcat起動時に呼ばれる「catalina.sh」で設定した例(80行目くらいに記述)。

-----
JAVA_OPTS=-Dorg.apache.catalina.SESSION_COOKIE_NAME=JSESSIONID2
-----

HttpSessionをSessionIDから取得

そもそも標題のような要件が発生すること自体まれだと思うのだが、筆者が実際に陥った環境なのでまとめました。

■用意するもの
HttpSessionListener - セッションの作成/破棄をハンドリングするリスナ。
ServletContextListener - コンテキストの初期化をハンドリングするリスナ。

■ServletContextListenerの実装
contextInitialized()をオーバライドし、ハッシュマップをコンテキストスコープに保存。
保存した「activeUsers」をセッションIDでセッションを取得する為のオブジェクトとして使う。

-----
public class MyContestListener implements ServletContextListener {

@Override
    public void contextInitialized(ServletContextEvent event) {
        ServletContext context = event.getServletContext();

        HashMap activeUsers = new HashMap();
        context.setAttribute("activeUsers", activeUsers);
    }

-----

■HttpSessionListener
セッションの作成、破棄した時に呼ばれるメソッドをオーバライド。
セッションが作成されたらそれをセッションIDをキーにしてハッシュマップに保存。
セッションが破棄されたらセッションIDをキーにして削除。

-----
public class SessionListener implements HttpSessionListener{
    public void init(ServletConfig config){
    }

    public void sessionCreated(HttpSessionEvent event){
        HttpSession    session = event.getSession();
        ServletContext context = session.getServletContext();
        HashMap activeUsers = (HashMap)context.getAttribute("activeUsers");

        activeUsers.put(session.getId(), session);
        context.setAttribute("activeUsers", activeUsers);
    }

    public void sessionDestroyed(HttpSessionEvent event){
        HttpSession    session = event.getSession();
        ServletContext context = session.getServletContext();
        HashMap activeUsers = (HashMap)context.getAttribute("activeUsers");
        activeUsers.remove(session.getId());
    }

-----

■web.xmlに登録
filterの上に定義。

-----
    <listener>
        <listener-class>
          example.listener.MySessionListener
        </listener-class>
    </listener>

    <listener>
        <listener-class>
          example.listener.MyContestListener
        </listener-class>
    </listener>
-----

■セッションの取得
サーブレットでセッションIDからセッションを取得する処理。
今回は、Struts2で実装。ServletContextの取得方法が少しややこしい。

----
ActionContext ac = ActionContext.getContext();
ServletContext sc = (ServletContext)ac.get(StrutsStatics.SERVLET_CONTEXT);
HashMap sMap = (HashMap)sc.getAttribute("activeUsers");
HttpSession session2 = (HttpSession)sMap.get(session.getId());
-----

レプリケーション環境でも問題なく動きました。セッションを生成したタイミングでクラスタリングメンバの
HttpSessionListener#sessionCreated()が呼ばれていました。
セッションが二重持ちになってしまうのが気持ち悪いがセッションIDから取得する必要がある場合は、
このような実装で対応するのもありかも。

WebViewとHttpClientのCookie共有(その2)

前回、HttpClientでリクエスト→クッキー保存→Webviewで共有のパターンを書いたが、
今回はその逆のパターンでWebViewでリクエスト→Cookie保存→HttpClientで共有の方法を紹介する。
WebViewでログインしてから、HttpClientでWebViewと同一サイトで認証が必要な処理等がある場合に
そのHttpClientのリクエストが認証をパスする時に使えたりする(あまり需要はなさそうだが)。

今回のパターンの共有には以下のクラスを使う。

■共有に使うクラス
WebViewClient - WebViewのクライアント
CookieManager - Cookie管理のクラス(取得/設定等)
BasicClientCookie - ユーザが作成可能なCookieクラス
CookieStore - HttpClientのクッキーの保管場所

■ソース
1.
まずは、DefaultHttpClientをActivityのフィールドに定義する。
後でWebViewClientでCookieを設定する時に参照する為。

public class XXXActivity extends Activity {

    private WebView webView;
    private DefaultHttpClient httpClient = new DefaultHttpClient();


2.
WebViewClientのonPageFinished()をオーバライドし、Cookieが保存されるであろうリクエストが
完了した後にHttpClientにCookieを設定する。
こんな感じ(WebViewClientに実装)。

@Override
public void onPageFinished(WebView view, String url) {

    // Cookieの保存が予想されるURLの場合
    if (url.indexOf(Cookie保存が予想されるURL) > -1) {
        // WebViewのCookieを取得
        String cookie = CookieManager.getInstance().getCookie(url);
        String[] oneCookie = cookie.split(";");
        for (String namAndVal : oneCookie) {
            namAndVal = namAndVal.trim();
            String[] cookieSet = namAndVal.split("=");
            // Cookieを作成
            BasicClientCookie bCookie = new BasicClientCookie(cookieSet[0], cookieSet[1]);
            bCookie.setDomain("ドメイン");
            bCookie.setPath("/");
            // CookieStoreを取得
            CookieStore store = httpClient.getCookieStore();
            // Cookieを追加
            store.addCookie(bCookie);
        }                
    }
:
}

まず、Cookieの取得はCookieManagerでする。
「;」でのsplit()は必須ではないのだが、Cookieが複数取得できる場合は「NAME=VALUE ; NAME=VALUE」の
形式で取得されるので書く名前と値のセットごとに分割する。
BasicClientCookieで任意のCookieを作成する。
この時も名前と値を別々に設定する必要があるので「名前=値」を「=」で分割する。
後は、ドメインとパスを設定する(パスは前方一致なので/にしとけば常に送信される)
CookieStore経由で作成したBasicClientCookieを追加する。

3.
WebViewに上記で実装したWebViewClientを設定してあげる。

webView.setWebViewClient(webViewClient);

4.
DefaultHttpClientでリクエスト。

HttpPost post = new HttpPost(リクエストするURL);
HttpResponse res = httpClient.execute(post);

WebViewClientでCookieが設定された後でリクエストすれば、最初からリクエスト送信時にCookieも送信される。
今回のパターンの場合は、CookieSyncManagerで簡単に処理できないので少し面倒。

S2JDBCでパラメータのMapを流れるインターフェースで書く

S2JDBCのSQLファイルを使う場合、バインドするパラメータにMAPを使う事が出来るのだが、
このMapの作成を流れるようなインターフェースで書けるようにS2JDBではParameterクラスというのが
用意されている。
使い方は以下。

1.staticインポート
Parameterクラスをstaticインポートする。

import static org.seasar.extension.jdbc.parameter.Parameter.*;

public class XXXService extends AbstractService {


2.Mapを流れるインターフェースで記述。
-----
jdbcManager.updateBySqlFile("SQLファイルのパス",
    params("key1", value1)
              .$("key2", value2)
              .$("key3", value3).$()).execute();
-----

マップのキーはSQLファイルのパラメータ名と一致させる。
最後に「.$()」を記述するのを忘れない事。
忘れると$(key, value)で返却されるMaps(Mapではない)のインスタンスとなる為、実行時に例外が発生する。

Tomcat6のCluster構成(バーチャルホスト編)

前回、構成したTomcatの2台のクラスタリングをApacheHTTPServerのVirtualHostで動作させてみる。

■環境
Windows XP
Apache Tomcat 6.0.32
Apache HTTP Server 2.2.17
└mod_proxy
└mod_proxy_balancer
└mod_proxy_ajp

■Apacheの設定
1.httpd-vhosts.confのインクルード
バーチャルホストの設定を記述するファイル「httpd-vhosts.conf」をhttpd.confで
インクルードする。
「httpd.conf」の以下のコメントアウトを解除

# Virtual hosts
Include conf/extra/httpd-vhosts.conf

2.VirtualHostの定義
今回はTomcat上で動作するWebアプリのコンテキストが「/session-rep-test」の
ものをバランシングした上でバーチャルホストで参照できるようにする。
設定は「httpd-vhosts.conf」に以下を記述。

-----
<VirtualHost *:80>
    ServerName makochi.com
    
    ProxyPass / balancer://test/
    ProxyPassReverse / http://makochi.com/session-rep-test/
    ProxyPassReverseCookiePath /session-rep-test /
    
    <Proxy balancer://test/>
        BalancerMember ajp://localhost:8009/session-rep-test/ loadfactor=10
        BalancerMember ajp://localhost:8010/session-rep-test/ loadfactor=10
    </Proxy>
    
    ErrorLog "logs/makochi.com-error.log"
    CustomLog "logs/makochi.com-access.log" common
</VirtualHost>
-----

重要なのは「ProxyPassReverseCookiePath」の設定。
ProxyPassで「/」へのアクセスをTomcatの「ajp://localhost:80xx/session-rep-test」へ振り分けている為、
アプリケーションサーバ(Tomcat)で「Set-Cookie」を発行する際のpathにコンテキストの「/session-rep-test」が設定される。
そうするとCookie情報としては「JSESSIONID ~ path=/session-rep-test」で保存してしまい、次回以降のクライアントからのリクエストでURLが「/session-rep-test」にマッチしないためセッションIDが送信されない。
つまり、毎回アプリケーションサーバ側では新しいセッションを生成してしまう。

これを防止する為にSet-Cookieヘッダ送信時のpathを書き換える設定を「ProxyPassReverseCookiePath」でする。
今回は「/session-rep-test」→「/」に書き換える設定。

これでクライアントからセッションIDを送信出来るようになる。

■hosts
最後にDNS登録とかしているわけではないので、バーチャルホストのIPをhostsファイルに追加。

hostsファイルの場所:
C:\WINDOWS\system32\drivers\etc\hosts
-----
127.0.0.1 makochi.com
-----

Tomcat6のCluster構築

今回は以下の環境でTomcatのクラスタリングを構成してみる。
同一マシン上にTomcatを2台立ててその間でSessionをレプリケーションします。

■環境
Windows XP
Apache Tomcat 6.0.32
Apache HTTP Server 2.2.17
└mod_proxy
└mod_proxy_balancer
└mod_proxy_ajp

■Tomcatの設定(2台)
1.インストール
server.xmlを起動オプションで指定して1台を仮想的に2台にする方法もあるようだが、
とりあえず今回は実体を2台配置する。
Tomcatは以下の場所にそれぞれインストール(以下、TOMCAT_HOME)

C:\srv\tomcat01\apache-tomcat-6.0.32
C:\srv\tomcat02\apache-tomcat-6.0.32

2.server.xmlの編集
ServerのポートとConnectのポート番号を2台で被らない様に変更する。
8080、8081は利用しないのでコメントアウトしてもよい。
(2台目のTomcatだけ変更)

2台目:
<Server port="8006" shutdown="SHUTDOWN">

<Connector port="8081" protocol="HTTP/1.1"
        connectionTimeout="20000"
        redirectPort="8443" />

<Connector port="8010" protocol="AJP/1.3" redirectPort="8443" />

4.Apacheのロードバランシングの設定
mod_proxyとmod_proxy_balancerを使う。
とりあえず、sticksessionの設定はしない。

httpd.confの以下のLoadModuleのコメントアウトを解除。
一番最後の行にセクションを追加。
今回はWebアプリへ以下のURLでアクセスした場合に配下のTomcatへバランシングする設定。

URL:
http://localhost/session-rep-test/

-----
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_ajp_module modules/mod_proxy_ajp.so
LoadModule proxy_balancer_module modules/mod_proxy_balancer.so

<IfModule mod_proxy_ajp.c>
<IfModule mod_proxy_balancer.c>
    <Location /session-rep-test/>
        ProxyPass balancer://session-rep-test/ nofailover=Off
    </Location>

    <Proxy balancer://session-rep-test/>
        BalancerMember ajp://192.168.1.11:8009/session-rep-test/ loadfactor=10
        BalancerMember ajp://192.168.1.11:8010/session-rep-test/ loadfactor=10
    </Proxy>
</IfModule>
</IfModule>
-----

■Tomcatのレプリケーション設定
各Tomcatのserver.xmlの要素の中に要素と要素を記述。
Tomcatのマニュアルでは要素をコメントアウトするだけで最小限の設定は済むと記述されていたが、
自分の試した環境では上手くレプリケーションされていなかった。
MembershipやRecieverは記載しなくても今回の環境では動作した。

<Engine name="Catalina" defaultHost="localhost">

    <!--For clustering, please take a look at documentation at:
            /docs/cluster-howto.html (simple how to)
            /docs/config/cluster.html (reference documentation) -->

    <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster">

    <Manager className="org.apache.catalina.ha.session.DeltaManager"
                             expireSessionsOnShutdown="false"
                             notifyListenersOnReplication="true"/>

    </Cluster>


■Webアプリのレプリケーション設定
web.xmlに以下の記述を追加。
今回は要素の直前に追記した。
これがないとレプリケーションの対象とならないらしい(未確認)

<distributable/>

■TomcatとApacheを起動
Tomcat2台→ApacheHTTPServerの順に起動。

以下は起動時のTomcatのログ

1台目:
-----
2011/02/13 0:55:29 org.apache.catalina.core.AprLifecycleListener init
情報: The APR based Apache Tomcat Native library which allows optimal performance~
2011/02/13 0:55:30 org.apache.coyote.http11.Http11Protocol init
情報: Coyote HTTP/1.1を http-8080 で初期化します
2011/02/13 0:55:30 org.apache.catalina.startup.Catalina load
情報: Initialization processed in 2208 ms
2011/02/13 0:55:31 org.apache.catalina.core.StandardService start
情報: サービス Catalina を起動します
2011/02/13 0:55:31 org.apache.catalina.core.StandardEngine start
情報: Starting Servlet Engine: Apache Tomcat/6.0.32
2011/02/13 0:55:31 org.apache.catalina.ha.tcp.SimpleTcpCluster start
情報: Cluster is about to start
2011/02/13 0:55:31 org.apache.catalina.tribes.transport.ReceiverBase bind
情報: Receiver Server Socket bound to:/192.168.1.11:4000
2011/02/13 0:55:31 org.apache.catalina.tribes.membership.McastServiceImpl setupSocket
情報: Setting cluster mcast soTimeout to 500
2011/02/13 0:55:31 org.apache.catalina.tribes.membership.McastServiceImpl waitForMembers
情報: Sleeping for 1000 milliseconds to establish cluster membership, start level:4
2011/02/13 0:55:32 org.apache.catalina.tribes.membership.McastServiceImpl waitForMembers
情報: Done sleeping, membership established, start level:4
2011/02/13 0:55:32 org.apache.catalina.tribes.membership.McastServiceImpl waitForMembers
情報: Sleeping for 1000 milliseconds to establish cluster membership, start level:8
2011/02/13 0:55:33 org.apache.catalina.tribes.membership.McastServiceImpl waitForMembers
情報: Done sleeping, membership established, start level:8

情報: Webアプリケーションディレクトリ ROOT を配備します
2011/02/13 0:55:37 org.apache.catalina.ha.session.JvmRouteBinderValve start
情報: JvmRouteBinderValve started
情報: Server startup in 6396 ms
2011/02/13 0:56:02 org.apache.catalina.tribes.io.BufferPool getBufferPool
情報: Created a buffer pool with max size:104857600 bytes of type:org.apache.catalina.tribes.io.BufferPool15Impl
2011/02/13 0:56:03 org.apache.catalina.ha.tcp.SimpleTcpCluster memberAdded
情報: Replication member added:org.apache.catalina.tribes.membership.MemberImpl[tcp://{192, 168, 1, 11}:4001,{192, 168, 1, 11},4001, alive=1042,id={4 29 -40 -125 5 -14 72 26 -79 117 60 114 74 -77 21 111 }, payload={}, command={}, domain={}, ]
-----

2台目:
-----
2011/02/13 0:56:00 org.apache.catalina.core.AprLifecycleListener init
情報: The APR based Apache Tomcat Native library which allows optimal performance~
2011/02/13 0:56:02 org.apache.coyote.http11.Http11Protocol init
情報: Coyote HTTP/1.1を http-8081 で初期化します
2011/02/13 0:56:02 org.apache.catalina.startup.Catalina load
情報: Initialization processed in 2279 ms
2011/02/13 0:56:02 org.apache.catalina.core.StandardService start
情報: サービス Catalina を起動します
2011/02/13 0:56:02 org.apache.catalina.core.StandardEngine start
情報: Starting Servlet Engine: Apache Tomcat/6.0.32
2011/02/13 0:56:02 org.apache.catalina.ha.tcp.SimpleTcpCluster start
情報: Cluster is about to start
2011/02/13 0:56:02 org.apache.catalina.tribes.transport.ReceiverBase bind
情報: Receiver Server Socket bound to:/192.168.1.11:4001
2011/02/13 0:56:02 org.apache.catalina.tribes.membership.McastServiceImpl setupSocket
情報: Setting cluster mcast soTimeout to 500
2011/02/13 0:56:02 org.apache.catalina.tribes.membership.McastServiceImpl waitForMembers
情報: Sleeping for 1000 milliseconds to establish cluster membership, start level:4
2011/02/13 0:56:02 org.apache.catalina.ha.tcp.SimpleTcpCluster memberAdded
情報: Replication member added:org.apache.catalina.tribes.membership.MemberImpl[tcp://{192, 168, 1, 11}:4000,{192, 168, 1, 11},4000, alive=31386,id={8
0 122 -101 -113 -42 26 65 73 -96 -32 -2 27 -69 -116 78 25 }, payload={}, command={}, domain={}, ]
2011/02/13 0:56:03 org.apache.catalina.tribes.membership.McastServiceImpl waitForMembers
情報: Done sleeping, membership established, start level:4
2011/02/13 0:56:03 org.apache.catalina.tribes.membership.McastServiceImpl waitForMembers
情報: Sleeping for 1000 milliseconds to establish cluster membership, start level:8
2011/02/13 0:56:03 org.apache.catalina.tribes.io.BufferPool getBufferPool
情報: Created a buffer pool with max size:104857600 bytes of type:org.apache.catalina.tribes.io.BufferPool15Impl
2011/02/13 0:56:04 org.apache.catalina.tribes.membership.McastServiceImpl waitForMembers
情報: Done sleeping, membership established, start level:8

情報: Starting clustering manager at /session-rep-test
2011/02/13 0:56:05 org.apache.catalina.ha.session.DeltaManager getAllClusterSessions
警告: Manager [localhost#/session-rep-test], requesting session state from org.apache.catalina.tribes.membership.MemberImpl[tcp://{192, 168, 1, 11}:40
00,{192, 168, 1, 11},4000, alive=34520,id={80 122 -101 -113 -42 26 65 73 -96 -32 -2 27 -69 -116 78 25 }, payload={}, command={}, domain={}, ]. This op
eration will timeout if no session state has been received within 60 seconds.
2011/02/13 0:56:06 org.apache.catalina.ha.session.DeltaManager waitForSendAllSessions
情報: Manager [localhost#/session-rep-test]; session state send at 11/02/13 0:56 received in 351 ms.

2011/02/13 0:56:08 org.apache.catalina.ha.session.JvmRouteBinderValve start
情報: JvmRouteBinderValve started

情報: Server startup in 7066 ms
-----

1台目ダウン→2台目のログ
-----
2011/02/13 1:39:41 org.apache.catalina.tribes.group.interceptors.TcpFailureDetector memberDisappeared
情報: Verification complete. Member disappeared[org.apache.catalina.tribes.membership.MemberImpl[tcp://{192, 168, 1, 11}:4000,{192, 168, 1, 11},4000,
alive=2650311,id={80 122 -101 -113 -42 26 65 73 -96 -32 -2 27 -69 -116 78 25 }, payload={}, command={66 65 66 89 45 65 76 69 88 ...(9)}, domain={}, ]]

2011/02/13 1:39:41 org.apache.catalina.ha.tcp.SimpleTcpCluster memberDisappeared
情報: Received member disappeared:org.apache.catalina.tribes.membership.MemberImpl[tcp://{192, 168, 1, 11}:4000,{192, 168, 1, 11},4000, alive=2650311,
id={80 122 -101 -113 -42 26 65 73 -96 -32 -2 27 -69 -116 78 25 }, payload={}, command={66 65 66 89 45 65 76 69 88 ...(9)}, domain={}, ]
-----

■考察
【Receiver】
Receiverを定義しなくても自動的にポート番号をずらしてListenしている事がわかる。

1台目 - 情報: Receiver Server Socket bound to:/192.168.1.11:4000
2台目 - 情報: Receiver Server Socket bound to:/192.168.1.11:4001

マニュアルにも以下のように説明されている。
「in most cases Tomcat is smart enough to resolve this on it's own by autodetecting available ports in the range 4000-4100」

【メンバ追加】
既に1台目が起動している為、2台目のTomcatは起動時に1台目をメンバに追加。
1台目は2台目が起動した後に1台目をメンバとして追加。

2台目:
2011/02/13 0:56:02 org.apache.catalina.ha.tcp.SimpleTcpCluster memberAdded
情報: Replication member added:org.apache.catalina.tribes.membership.MemberImpl[tcp://{192, 168, 1, 11}:4000,{192, 168, 1, 11},4000, alive=31386,id={8
0 122 -101 -113 -42 26 65 73 -96 -32 -2 27 -69 -116 78 25 }, payload={}, command={}, domain={}, ]

1台目:
2011/02/13 0:56:03 org.apache.catalina.ha.tcp.SimpleTcpCluster memberAdded
情報: Replication member added:org.apache.catalina.tribes.membership.MemberImpl[tcp://{192, 168, 1, 11}:4001,{192, 168, 1, 11},4001, alive=1042,id={12
4 29 -40 -125 5 -14 72 26 -79 117 60 114 74 -77 21 111 }, payload={}, command={}, domain={}, ]

【JvmRouteの設定】
JvmRouteの設定もよろしくやってくれてそうな気配。
stickysessionにしない場合はあまり関係なさそうだが。

2011/02/13 0:56:08 org.apache.catalina.ha.session.JvmRouteBinderValve start
情報: JvmRouteBinderValve started

【フェイルオーバー】
メンバのダウンを検知している模様。

2011/02/13 1:39:41 org.apache.catalina.tribes.group.interceptors.TcpFailureDetector memberDisappeared
情報: Verification complete. Member

■その他
TomcatではClusterを構成する場合、以下の2つのManagerが利用できる。
デフォルトでは「DeltaManager」を使う設定になっているようだが、Clusterの台数が多くなってくると
パフォーマンスに影響がでそう。

DeltaManager:
全てのメンバでレプリケーションを行う(台数が多いと高負荷)。

BackupManager:
レプリケーション用のノードを1台用意し、そこにセッションをレプリケーションする(単一障害点になるかも)

とりあえず、最低限の定義情報で行ったのでチューニングとかを考えるとまだまだ研究の余地がありそう。

■参考
http://tomcat.apache.org/tomcat-6.0-doc/cluster-howto.html

S2JDBC-Genで自動生成したServiceクラスでSQLファイルを使用する場合の注意点

S2JDBC-Genで自動生成したServiceクラスでSQLファイルを使用とするとファイルパスの先頭に
「META-INF/sql/~」が自動的に添加されてしまい、指定したSQLファイルが見つからない。
原因は、Serviceクラスの親クラスのupdateBySqlFile()メソッドで以下の通り「sqlFilePathPrefix」変数の
値を先頭に添加している。

■S2AbstractService#updateBySqlFile()
protected SqlFileUpdate updateBySqlFile(String path, Object parameter) {
    return jdbcManager.updateBySqlFile(sqlFilePathPrefix + path, parameter);
}

この「sqlFilePathPrefix」の値は、S2AbstractServiceのsetEntityClass()メソッドで設定されており、
このメソッドをサブクラスのエンティティのServiceクラスでオーバライドすれば、パスの先頭に余計な
文字列が添加されるのを防ぐことが出来る。

■S2AbstractService#setEntityClass()
protected void setEntityClass(Class entityClass) {
    this.entityClass = entityClass;
    sqlFilePathPrefix = "META-INF/sql/"
        + StringUtil.replace(entityClass.getName(), ".", "/") + "/";
}

↓以下の通りオーバライド

■サブクラスのService#setEntityClass()
@Override
protected void setEntityClass(Class entityClass) {
    this.entityClass = entityClass;
    sqlFilePathPrefix = "";
}

S2JDBC-GenでServiceクラスを自動生成してくれるのは有難いのだが、このような仕様は不便だな。
今実装しているプロジェクトでは、自動生成したメソッドの利用頻度も低いし、jdbcManagerをラップされる
のも何かウザく感じてきたからServiceを自動生成して利用するのやめようかな。
最近は、余計なものを作るのはやめようって流れだし。

ProgressBarの中央表示

前回RelativeLayoutで中央表示する例だとActivityの起動時ではProgressBarを中央表示
する事が出来ましたが、一度、Viewを表示してしまうとそれ以降はProgressBarの表示が
出来なくなる欠点がありました。
これをFrameLayoutを利用すると任意のタイミングで表示出来るようになります。

以下はWebViewを使ってページロード中はProgressBarを表示し、ロード完了後に非表示にする例

■レイアウトXML
-----
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent" android:layout_height="fill_parent">
    <WebView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/web_view"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />
    <ProgressBar android:id="@+android:id/progress_bar"
    style="?android:attr/progressBarStyle" android:layout_width="wrap_content"
    android:layout_height="wrap_content" android:indeterminate="true"
    android:layout_gravity="center"/>
</FrameLayout>
-----

FrameLayoutに配置する事で後から追加したProgressBarをWebViewと重ねて表示させることができる。
中央配置は「layout_gravity="true"」。

■Activity
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.mail);
    // プログレスバー表示
    progressBar = (ProgressBar)findViewById(R.id.progress_bar);
    progressBar.setVisibility(View.VISIBLE);
  :
}

■WebViewClient
private WebViewClient webViewClient = new WebViewClient() {

    @Override
    public void onPageFinished(WebView view, String url) {
        progressBar.setVisibility(View.GONE);
    }

    @Override
    public void onPageStarted(WebView view, String url, Bitmap favicon) {
        progressBar.setVisibility(View.VISIBLE);
    }
};

WebViewに上記のWebViewClientを設定すればOK。

FrameLayoutの重ねて表示できる仕組みは他にも色々と使い道がありそう。
プロフィール

まこち

Author:まこち
スマートフォンのアプリ開発やWebサイト構築等を仕事や趣味でやっています。
最近はグラフデータベースも始めました。

最新記事
最新コメント
最新トラックバック
月別アーカイブ
カテゴリ
検索フォーム
RSSリンクの表示
リンク
ブロとも申請フォーム

この人とブロともになる

QRコード
QR
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。