2015年2月9日月曜日

HTML5で簡単にandroidアプリを作る

FirefoxOSアプリはHTML5で作成する。
FirefoxOSアプリで作成したアプリをそのままアンドロイドアプリに移植したいなと思い、
アンドロイドのwebviewを使ってhtmlを表示させることにした。
ただし、僕はwebサーバを建てて、そこにFirefoxOSアプリを配布してる(ホスト型アプリ)ので、アンドロイドアプリもwebサーバからhtmlを取得することを想定。

やりたいことは、以下の2点。
・geolocation(javascriptで位置情報を取得するapi)の有効
・localstrageの有効

メインのactivityクラス(Main.java)は以下の通り。
 21
 22public class Main extends Activity {
 23    final Activity activity = this;
 24
 25    // WebView宣言 これがハイブリッドアプリの要                                                                                                             
 26    WebView webview;
 27
 28    public static final int END_CONFIRM_DIALOG = 0;
 29
 30    @Override
 31    public void onCreate(Bundle savedInstanceState) {
 32        super.onCreate(savedInstanceState);
 33
 34        // WebViewの親になる最上位のwidget                                                                                                                  
 35        LinearLayout layout = new LinearLayout(this);
 36
 37        // 最初に開くURL                                                                                                                                    
 38        // もし何らかの条件に基づいてURLを動的に変えたいならこのへんに処理を書く                                                                            
 39        String targetUrl = "http://接続させたいURL";
 40
 41        // WebView 作る                                                                                                                                     
 42        webview = new WebView(this);
 43
 44        // JavaScript をオンに                                                                                                                              
 45        webview.getSettings().setJavaScriptEnabled(true);

 46        webview.getSettings().setGeolocationEnabled(true);
 47
 48        // localstrageの利用                                                                                                                                
 49        String databasePath = this.getApplicationContext().getDir("localstorage", Context.MODE_PRIVATE).getPath();
 50        webview.getSettings().setDomStorageEnabled(true);
 51        webview.getSettings().setDatabaseEnabled(true);
 52        webview.getSettings().setDatabasePath(databasePath);                                                                                              
 56
 57        // ズームを有効化するか                                                                                                                             
 58        webview.getSettings().setSupportZoom(false);
 59
 60        // スクロールバーが外側に表示されないようにする                                                                                                     
 61        webview.setScrollBarStyle(WebView.SCROLLBARS_INSIDE_OVERLAY);
 62
 63        // WebView クライアント設定。これで画面遷移がアプリ内でハンドルされる                                                                               
 64        webview.setWebViewClient(new WebViewClient() {
 65            // WebViewがエラーに直面した時の処理                                                                                                            
 66            public void onReceivedError(WebView view, int errorCode,
 67                    String description, String failingUrl) {
 68                // とりあえずエラーの説明をToastで表示                                                                                                      
 69                Toast.makeText(activity, "エラー発生 詳細:" + description,
 70                        Toast.LENGTH_LONG).show();
 71            }
 72
 73            @Override
 74            public boolean shouldOverrideUrlLoading(WebView view, String url) {
 75                return false;
 76            }
 77        });
 78
 79        // 進捗状況表示のためにProgress barを用意                                                                                                           
 80        getWindow().requestFeature(Window.FEATURE_PROGRESS);
 81        // 進捗状況をタイトルバーに表示                                                                                                                     
 82        webview.setWebChromeClient(new WebChromeClient() {
 83            public void onProgressChanged(WebView view, int progress) {
 84                // WebChromeClient#onProgressChangedのprogressは0から100なのに対し、                                                                        
 85                // Activity#setProgressは0から10000の範囲で指定するので100倍する                                                                            
 86                activity.setProgress(progress * 100);
 87            }
 88
 89            @Override
 90            public void onGeolocationPermissionsShowPrompt(String origin,
 91                    Callback callback) {
 92                callback.invoke(origin, true, false);
 93            }
 94        });
 95
 96        // 指定したURLをWebViewに読み込ませる                                                                                                               
 97        webview.loadUrl(targetUrl);
 98
 99        // WebViewをLayoutにくっつけ描画                                                                                                                    
100        layout.addView(webview);
101        setContentView(layout);
102    }
103
104    // 戻るキーが押された時の処理                                                                                                                           
105    @Override
106    public boolean onKeyDown(int keyCode, KeyEvent event) {
107        // 戻れるページがあるかチェック                                                                                                                     
108        if (keyCode == KeyEvent.KEYCODE_BACK && webview.canGoBack() == true) {
109            webview.goBack(); // あったら前のページに戻る                                                                                                   
110            return true;
111        }
112        return super.onKeyDown(keyCode, event);
113    }
114
115    // 終了しそうになる時に……                                                                                                                             
116    @Override
117    public void finish() {
118        // 確認ダイアログを出す                                                                                                                             
119        showDialog(END_CONFIRM_DIALOG);
120    }
121
122    // 終了処理                                                                                                                                             
123    public void endApp() {
124        super.finish();
125    }
126
127    // 終了確認ダイアログを出す                                                                                                                             
128    @Override
129    protected Dialog onCreateDialog(int id) {
130        switch (id) {
131        case END_CONFIRM_DIALOG:
132            return new AlertDialog.Builder(this)
133                    .setTitle("確認")
134                    .setMessage("終了しますか?")
135                    // Yesボタンの設定                                                                                                                      
136                    .setPositiveButton("はい",
137                            new DialogInterface.OnClickListener() {
138                                // Yesが押された時の処理                                                                                                    
139                                public void onClick(DialogInterface dialog,
140                                        int whichButton) {
141                                    // 終了処理を呼び出す                                                                                                   
142                                    endApp();
143                                }
144                            })
145                    // Noボタンの設定                                                                                                                       
146                    .setNegativeButton("いいえ",
147                            new DialogInterface.OnClickListener() {
148                                // Noが押された時の処理(何もしない)                                                                                       
149                                public void onClick(DialogInterface dialog,
150                                        int whichButton) {
151                                }
152                            }).create();
153        }
154        return null;
155    }
156}


ポイント1:javascriptを有効。
 44        // JavaScript をオンに                                                                                                                              
 45        webview.getSettings().setJavaScriptEnabled(true);


ポイント2:geolocationを有効
 46        webview.getSettings().setGeolocationEnabled(true);
 47

ポイント3:localstrageを有効
 48        // localstrageの利用                                                                                                                                
 49        String databasePath = this.getApplicationContext().getDir("localstorage"Context.MODE_PRIVATE).getPath();
 50        webview.getSettings().setDomStorageEnabled(true);
 51        webview.getSettings().setDatabaseEnabled(true);
 52        webview.getSettings().setDatabasePath(databasePath);                                                                                              


あと、AndroidManifest.xmlに以下を追記。
INTERNETはインターネットを利用するから必要。
ACCESS_FINE_LOCATIONとACCESS_COARSE_LOCATIONはgeolocationを利用するので必要。
 9    <uses-permission android:name="android.permission.INTERNET" />
10    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
11    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

【参考にしたサイト】