Android:javaScriptに関する仕様変更

jQuery問題集のHTMLがAndroidに表示できるようになったので
jQueryとの連携のプログラムを書いていたのですが、is11tでは機能するのに
nexus7では機能しません…。
以前にjavaScriptとの連携で利用したサンプルでは機能しているのに…、
 

JavascriptInterfaceの仕様変更

調べるとセキュリティを考慮してAndroid4.2.2から仕様変更されたようです。
以下のサイトが詳しいです。
→参考:UB Lab.さま「Nexus 7(Android 4.2.2)で、JavascriptInterfaceが動かない
 
JavascriptInterfaceのセキュリティの問題は以前から問題視されていたようで
それに対応するための処置のようです。問題に関しては以下のサイトが詳しいです。
→参考:AndroidのWebView#addJavascriptInterfaceは基本使わない方がいい、っていう話
 

loadUrlも禁止に

javaScript→Androidの接続はできたので、続いてAndroid→javaScriptの接続に
はいりました。ここでも実機のNexus7で機能しません。
 
調べるとAndroid4.4ではloadUrlが利用できなくなっているようです。
→参考:WebView on Android 4.4 – Changing font using JavaScript
 
しかし、この方法を利用してもダメでした。というかNexus7のバージョンを確認したら
4.3だったので、これが原因ではないようです。
ここで悩んだのですがnuxus7のバージョンを4.4にしました。
にもかかわらずダメでした。
 

意外な結末

原因を調べるために、jQuery問題集での作業をやめて簡単なサンプルを作成しました
android側に配置したbuttonをクリックするとhtml側のjavaScriptを実行する
シンプルなサンプルです。
スクリーンショット 2014-04-24 16.44.52
 
そして、これは見事に機能しました!
ここでjavaScript→Androidの直後にAndroid→javaScriptを実行すると
通信に失敗するのかな?と考えました。
 
しかし、ここで気が付いたのです。iOSではjavaScriptからiOSのメソッドが実行
できないからjavaScript→Androidの直後にAndroid→javaScriptを利用していた
だけで。直接メソッドが実行できるAndroidなら返値を貰うだけでよいのではないか!
 
ということで通信が失敗する理由は分かりませんが、問題は解決しました。
この問題が今後に響きそうなら原因を追及するのですが、こんなイレギュラーなiOS
向けの処理はAndroidに必要ないので究明はやめました。
 

Android4.xでのloadUrl

しかし関係有りそうな記事も見つかったのでメモ。
Android4.xではloadUrlでパラメータが渡せなくなっているようです。
私がダメだったサンプルではjavaScriptを直接実行して引数を渡しているので、
まったく同じ分けではないのですが…。
→参考:Android4.0のWebviewでURLパラメータが渡せない件について
 

Android4.4のWebView

Android4.4のWebViewは色々変更されているようです。以下のサイトが詳しいです。
→参考:Migrating_to_WebView_in_Android_4.4.md
 

touchcancelの追加

nexus7の実機でボタンをドラッグするようにタップするとONになったまま
になる現象に出会いました。機能的には問題ないからスルーしようかとも思った
のですが、上記の問題を調べている途中に原因が分かりました。
以下のサイトにある「touch end」だけでなく「touch cancel」でもOFFに戻す
ようにしました。この仕様変更によりリスト画面のようにボタンがたくさん配置されている
ところでスクロールさせる時、ボタンの表示がONになってしまうのを避けることができます。
しかしタップの際、すこしドラッグが入ってしまうクセのある方は、タップがキャンセル
されてしまうことがあります。個人的には昔の仕様の方が好きです。
→参考:Handling Touch Events in JavaScript
 
 
 

android:viewport

Android版jQuery問題集

やっとhtmlコンテンツをAndroid上に表示できるようになりました。
eclipseから実機のスクリーンショットを取ることができるので便利。
以下はis11tでコンテンツを表示した時のスクリーンショット。
nexus7のスクリーンショットは1920×1200もあるので省略。
 
スクリーンショット 2014-04-27 0.25.09
 
 

viewport関連のメモ

nexus7の実機でviewportの設定(width=320)が効かなくて色々試行錯誤しました。
エミュレータなら問題なく表示されるのですが実機ではダメなのです!
やはり実機を購入しておいて良かったかも。
 

viewportを有効にする

androidのwebViewはデフォルトではviewportの設定を無視するので
以下の処理を追加する必要があります。
しかし下記を設定しても実機のnexus7ではviewportを設定できません。
—————————————————–
Webview.getSettings().setLoadWithOverviewMode(true);
webview.getSettings().setUseWideViewPort(true);
—————————————————–
→参考:幽霊飛行船さま「WebViewでviewportサイズを指定する
 
 

一部の機種では幅の設定を320以下にできない

色々試行錯誤した結果、viewportが効かないのではなく320px以下の設定を
するとdevice-widthの値に強制的に設定される仕様ということが分かりました。
nexus7のdevice-widthは600px。コンテンツを正しく表示する値は320px
 
nexus7はミニタブレットのカテゴリなので、最悪の場合、対象から外しても良いかな?
と思ったのですが、以下の記事ではgalaxyS3/noteなども同じ問題があり
また、最近リリースされたスマホの解像度もgalaxy noteと同じなので、同じ問題が
あるかもしれず無視するわけにはいかなくなりました。
→参考:galaxy S3.. viewport meta tag doesn’t work
 

321なら

上記のサイトを参考にwidthの値を321に設定すれば、nexus7は理想に近くなるのですが
(右端に1pxの隙間ができます)。is11tでは正しく表示されなくなってしまいました。
なのでAndroid2.xでのみviewportを無効にするようにしたらposition:fixedが
効かなくなってフッターが正しく配置されません…。
 

cssのposition:fixedについて

上記のposition:fixedの問題を調べていたらandroid2.xではposition:fixedを
利用するためにはviewportでuser-scalable=no”を設定する必要がとのことです。
しかしviewportを設定しない場合、上記の記述が無くてもposition:fixedが効きました。
(is11tにて確認)
→参考:iPhone、Android position:fixed 対応状況と対応方法
  

jQueryで動的に拡大

上記のように「あっちを押せば、こっちが引っ込む」状態になり、どうするか困りました。
結局viewportの設定は一切利用せず、jQuery(javaScript)によってwindowの
幅から拡大率を算出して、動的にコンテンツを拡大するようにしました。
これなら検証できない未知の機種でも。対応できると思いますし。
以下のサイトが参考になりました。
→参考:iPhone / Andoird向けサイト制作のjQuery小技集
 

画面の向きの固定

viewportではないのですが、画面の向きを固定するのにも少しハマッタのでメモ。
画面の向きを固定するためには以下の設定をAndroidManifestに追加するのですが
—————————————————–
android:screenOrientation=”portrait”
—————————————————–
上記の設定はapplicationタグで行うのではなくactivityタグで行わないと
いけません。
 

 
 

Android:タイトルバーの非表示

タイトルバーを非表示にするのに2日半も費やしてしまいました…。

1日目

タイトルバーを非表示にする方法はgoogleで簡単に見つけることができます。
→参考:tekboy様「アプリのタイトルバーを非表示にする方法
 
しかし私の環境で、その設定を実行すると「Unfortunately,(アプリ名) has stopped.」と
表示されアプリが起動しません。世界は広いのに似たような問題に遭遇している方が見つかりま
せん。logを見ると「you need to use a theme.appcompat…」というテーマに関するアラー
トがあるので、これをキーワードに英語のサイトも調べますが、タイトルバーの非表示と絡んだ
情報は見つかりません…。英語を読むのは苦手なので頭痛がしてきました…。
 
プロジェクトを作成する際のアクティビティの選択で「Fullscreen Activitiy」を
選択するとタイトルバーやステータスバーが表示されないので、最悪の場合は
これを利用しようと思いつつ就寝。
スクリーンショット 2014-04-16 22.15.32
 

2日目

睡眠で気分がリフレッシュ!諦めずに頑張ろう!
ここまでくると私の環境がおかしいのではないか?と疑い始めwindowsにも開発環境を整えて
同じようにサンプルを作成。しかし結果はMacと同じ(MacとWinで動作が異なったら
もっと大変な気もします)。
 
機能確認した「Fullscreen Activitiy」ではタイトルバーが表示されないのだから
これを解読すればタイトルバーのみを消す方法が見つかるかも!とソースを解読しながら
必要ない部分はどんどん削除。しかし分からない…。
絶対可能だと思うものの時間切れ。就寝。
 

3日目

何気なく動作環境をAndroid4.xに絞ったプロジェクトで確認。すると冒頭のサイトで
紹介している手法が利用できる!アプリもきちんと起動する!
しかしAndroid2.xも今だに16%のシェアを持つため、2.xを切るわけにはいかない。
以下サイトの「Gingerbread」がAndroid2.3。
→参考:juggly.cnさま「Androidバージョン別シェア
 
ここで動作環境を4.xにするとバグのように増殖する「appcompat_v7」が
追加されないことに気が付く。でもってappcompat_v7の機能を調べると
古いAndroidでもタイトルバーにボタンやタブを設定できるライブラリとのこと。
→参考:yahoo知恵袋
 
やっと糸口が掴めました!。つまりタイトルバーの機能拡張をしてるくせに
タイトルバーを消すとはどういうこと!ということなのでしょう。たぶん。
ちなみにappcompat_v7は3月初旬に導入されたばかりです。
だから情報が見つからなかったのですね…。
 
というわけで、appcompat_v7の機能を使わないようにしたところ、無事にステータスバー
を残してタイトルバーだけ消すことができました。
 
 

具体的な方法をメモ

まずjavaファイルでActionBarActivityを継承している部分を
Activityに戻す。3月以前はActivityがデフォルトだったようです。
——————————————————–
public class MainActivity extends ActionBarActivity {

public class MainActivity extends Activity {
——————————————————–
でもって必要ないimportを削除していく。するとFragmentの処理がエラーになる。
しかしFragmentは利用しないので該当部分を削除。Fragmentの処理を全て削除すると
appcompat_v4のimportも必要なくなる。
 
appcompat_v4について調べるとAndroid3.xで追加されたFragmentの機能を
Android2.xで実現するもののようです。
 
Fragmentの処理を削除するとFragment_layout(デフォルトでhello worldが
置いてある所)が利用できなくなるが、jQuery問題集はフラグメントを利用しないのでOK。
実際、アクティビティのFullscreenもFragmentは利用していない。
 
 

まだ問題が続く…

現在jQuery問題集のhtmlをwebviewで表示するようにしているのですが
エミュレータではきちんと表示されるのに実機のnexus7だと小さく表示されてしまいます。
viewportの問題のようなのですが、原因がよく分かりません。
まだまだ前途は多難なようです。
 
 

Android:jQueryでのAjaxの使用

昨日の記事の続き。
 
昨日の記事でNexus7でjQueryのAjaxを利用するにはsetAllowUniversalAccessFromFileURLs
を利用すると書きましたが、これを追加すると逆にis11t(Android2.3)でアプリが起動しなく
なりました…。
 
でもってググって以下の記事を発見。
古いAndroidではsetAllowUniversalAccessFromFileURLsを利用できないので
バージョンによって処理を振り分けないといけないそうです。
→参考:Allow opening of local files in HTML5 Phonegapped Android app
 
Eclipseやjavaはxcodeやobjective-cよりも使いやすいのですが、対象のバージョンが
たくさんあって大変です…。
 
上記の問題は直ぐに解決できたのですが、いま以下2つの問題にぶつかり
ちょっと大変そうな感じです…。簡単そうな問題だと思ったのに…。
・Nexus7でviewportの設定が効かない
・アプリのタイトルバーが外せない
 
 
 

jQuery問題集:nexus7の購入

先週からjQuery問題集をAndroidアプリの作成方法を学んでいるわけですが
いよいよjQuery問題集のhtml&jQueryを読み込ませるところまで来ました!
 

Nexus7エミュレータで機能しない

実機のis11t(Android2.3)ではhtmlコンテンツを表示することができたのですが
nexus7エミュレータ(Android4.3)ではコンテンツが表示されせん!
htmlの読込自体は成功しているのですが、jQueryの処理の途中で止まってしまっている
のです。これは心当たりがあり、たぶん以下の問題だと検討を付けました。
→参考:永遠ログさま「Google ChromeでローカルファイルのAjax読み込みができない件
 
だからエミュレータだと機能しないけれど、実機では機能するんだよ!きっと!
と甘く考えていた先週末…。
 

nexus7の購入

Android2.xのシェアが16%ほどある現在、私のスマホis11tは検証機として有用です。
しかし2年前の実機でしか検証しないのも問題なので、新たな実機の購入を決意。
前述のエミュレータの問題が気になっていることも大きかったです。
 
iPhoneに対するiPodTouchのような機種がAndroidにも有ればよいのですが
見つからず、結局ミニタブレット機のnexus7を購入することにしました。
 
接続に少し戸惑いました。タブレット情報のビルド番号を7回タップしないと
接続できないなんて…。以下のサイトが参考になりました。
→参考:時々、失業SEの開発日誌さま「eclipseにNexus7を繋げてみた
 

実機でもnexus7でデータが読み込めない

nexus7でも実機ならis11tのように、問題なくローカルファイルが読み込めると
思っていたのですが、そうはいきませんでした。エミュレータとまったく同じ結果。
 
日本語キーワードでググっても情報が見つからず、英語で探すことに…。
そしたら簡単に見つかりました。以下の1行を追加するだけです。
※myWebViewはユーザーが作成したwebViewオブジェクト。
—————————————————–
myWebView.settings.setAllowUniversalAccessFromFileURLs(true);
—————————————————–
→参考:WebView Javascript cross domain from a local HTML file
 

雑記

1年前に購入したWindowsタブレット機は検証機としての他に、弥生会計で
会社の会計管理に役立っています。しかし、今回購入したミニタブレットって
検証以外に何の役に立つのだろう…。
今夏に予定されている新しい「kindle paperwhite」を購入しようと思っていた
けれど、その代わりになるかな?早速kindleアプリを入れて青空文庫を幾つか
ダウンロード。
 
なんだかしっくりしません。
私は文庫本を購入すると直ぐにカバーをはがして、結構ラフに本を扱うのですが
電子書籍だとラフに扱うこともできず気を使ってしまいます…。
 
ラフに扱っても壊れないで、ジーンズの後ポケット入れても安心な
電子書籍リーダーが有ればよいのに。
capture
真ん中がnexus7。必要性には疑問ですがレスポンスも良いですし機能的には満足です。
とくに電源を切る時に古いブラウン管のような演出がステキ。
→参考:google検索「タブレット 必要性
 
 
 

Android:メモ

ログ

デバッグに欠かせないログについては以下のサイトを参考にしました。
→参考:javaDrive様「ログの出力
表示できる値の型は文字列にしないといけないことに注意。
ログの種類(ERROR/WARNなど)が色々ありますが、これによりLogcatに出力される色が
変わってきます。下図の一番左(Level)がログの種類です。
スクリーンショット 2014-04-17 20.55.36
 
 

レイアウトについて

iOSとレイアウトに関する思想が違うので、ここに参考になったサイトをメモ。
html+jQueryでのコンテンツ作成では必要のない知識ですが。

Linearレイアウトが良さそう

シンプルなレイアウト案がたくさん載っている以下のサイトがおすすめ。
→参考:プログラミング雑記さま「LinearLayoutとRelativeLayoutの使い方をまとめてみた
Linearレイアウト以外のレイアウト方法は以下のサイト。
→参考:TechBooster様「レイアウトを使って配置する

文字の設定

レイアウトした要素に直接文字を設定するとエラーにはならないものの警告に
なってしまう。string.xmlに設定するのがよいらしい。
→参考:Y.A.Mの雑記帳さま「複雑な文字列をxmlで定義する
 
 

webView補足

webview関連のイベントハンドラはたくさんあるようです。
→参考:day after meetさま「AndroidのWebViewを使う
 
 
 

Android:メーラーの起動

アプリの連携をになうIntent

Androidでは他のアプリと連携するにはIntentクラスを利用するそうです。
メール専用というわけでなく、色々なことに利用できるとのこと。
メールに関しては以下のサイトが詳しいです。
→参考:暇なメモ帳さま「Androidでメールを送信する方法
 

iOSとの違い

iOSではメール用のライブラリが用意されていることもあり、Androidよりも機能が
充実しているような気がします。iOSではメーラーがデータを送信したか、破棄したかも
取得することが可能なので、jQuery問題集ではデータの送信を確認してから
復習データを削除していました。
→ブログ記事「iOS:メーラーの起動
しかしAndroidではデータを送りつけるだけのようで、その後を取得する手段が
見つかりません。iOSと異なりメーラーが複数有るので仕方がないのでしょうか?
 

注意点

エミュレータではメールの設定を先にしておかないとアプリが強制終了する。
これに結構はまってしまいました…。メールの設定はエミュレータ上のメールアイコンを
クリックすることで可能です。
実機でメールの設定がされていないことは少ないと思いますが、メールの設定が
されていない場合は実機でもアプリが強制終了する可能性があります。
 
実機ではメールを起動する際、複数のメーラーがあるとメーラーを選択する画面が
出てきます。参考のリンク先にあるように一部のキャリアメールでは正常に機能しない
ようです。
 

google playを開くのにも利用できる

iOS版のjQuery問題集Lite版には最初のページで有料版へのリンクを付けていますが
Android版にも付けようと思います。そしてgoogle playを開くのにもintentを
利用するそうです。以下のサイトでは色々なアプリを起動するサンプルがあります。
→参考:TechBoosterさま「Intentで画面遷移する
 
 

 

Android:サウンドについて

HTML5のAudioは利用できない?

Androidではサウンドの再生はhtml5のAudioを利用しようと思ったのですが
エミューレーターも実機も機能しませんでした。
Mac上のブラウザでは機能するのを確認しています。
あまり期待していなかったので、原因を追及することはやめて早々に
Androidでのサウンド再生について調べることにしました。
 

media playerとsound pool

参考になったのは以下のサイト。BGMのような長いサウンド再生に便利な
media playerとSEのような短いサウンドに便利なsound poolがあるそうです。
→参考:Developers.ID様「BGM や効果音を再生する
→参考:oundPoolクラスを使ってwav形式、ogg形式の効果音(SE)を鳴らしてみる
 

バックグラウンドでも鳴り続ける

サンプルを作成して動作検証したら、iOSと仕様が異なることに気が付きました。
ホームボタンをクリックして、アプリがバックグラウンドにまわってもBGMが鳴り続けるのです。
※iOSは自動的にフェードアウト
 
なので、バックグラウンドにまわった時はBGMを停止するように処理を書かなければいけません。
アプリの状態は以下のサイトが参考になりました。
→参考:JavaDrive様「アクティビティのライフサイクル
 
今回のサンプルでは、onCreateのタイミングでBGMとSEの設定をして
onStopのタイミングでBGMの一時停止。
onRestartのタイミングでBGMの再生(BGMがONのときだけ)
そしてアプリが完全に終了するonDestroyでBGMの停止とSEのリリースを
するようにしました。
 

サンプル動画


エミュレータだと動画のようにバックグラウンドにまわるとすぐにBGMが
停止するけれど、実機のis11tでは2〜3秒くらい止まらない…。
 

その他

サウンドデータはresフォルダ内にrawフォルダを作成して、そこに入れる。
次回はメーラーの起動に挑戦しようと思います。
 
 
 

Android:jQueryとの連携とデータ保存

Objective-Cより簡単

jQueryとの連携はiOSよりも簡単で使いやすいです!。iOSではjQueryから直接xcodeの
メソッドを実行することができず、URLの変更を介して情報を伝えていました。
しかしAndroidでは、jQueryから直接eclipseのメソッドを実行できます。
以下のサイトがシンプルで分かりやすかったです。
→参考:out of memory and health様「WebViewを使ったJAVAとJavascriptの連携方法
 
データの保存はiOSと似たような感じです。以下のサイトが分かりやすいです。
→参考:Monoist様「プリファレンスを使用したデータの保存
 

サンプル動画

ということで、jQueryとの連携とデータの保存を利用したサンプルを作成しました。
動画ではアプリに「save data」と入力しボタンをクリックした時点でデータが記憶されます。
そして一度アプリを終了し再びアプリを起動すると、保存した「save data」の文字が
表示されており、データの保存が成功していることが確認できます。

 
 
次回はサウンドの再生について学ぶ予定です。
 
 
  

Android:Macでeclipse

xcodeより導入は簡単!

これからjQuery問題集をandroidに移植するための学習を始めます。
環境の構築はxcodeよりも簡単なのでwebコンテンツが作成できる方は
試しに挑戦してみると良いかもしれません。
emu
 
xcodeでは有料のdévelopper programに加入しないと実機テストができませんが
eclipsではUSB接続しただけで簡単に実機テストができました。
私の実機はToshiba is11tで下図の最初にリストアップ。その下はエミュレータ。
is11t
 
  

躓いた所をメモ

とはいえ、少し躓いた部分があるのでメモ。まず参考にしたのは以下のサイト
掲載日時も新しく分かりやすいサイトです。
→参考:テックアカデミー様「MacでAndroidアプリの開発環境を構築する方法
 

eclipsにSDKをインストール

eclipsにAndroidのSDKをインストールするところで躓きました。
上記ページで「https://dl-ssl.google.com/android/eclipse/」を設定する部分が
あるのですが、ここでNextボタンがアクティブにならずクリックできない問題に悩みました。
 
で、色々確認したら何故か設定済みなようなのでスルーしました。
以下の様に「All items are installed」となっていたらスルーしてOKです。
※クリックで拡大
スクリーンショット-2014-04-13-0.37
 

エミュレータの高速化

googleで検索するとたくさん出てくるのですが上手くいきません。
→参考:google検索「mac android エミュレータ 高速化
 
最初はエミュレータが起動し「Android」のロゴまで表示されたのですが、その先に
進みませんでした。色々試していたら、機能していた高速化していないエミュレータまで
立ち上がらなくなってしまいました。
アプリを再起動してもエミュレータが起動せず困り果てたのですが、Macを再起動する
ことで回復しました。それ以来、高速化は諦めました…。
 

webViewの導入

以下のサイトを参考にwebページを表示しようとしたのですが躓きました。
→参考:okomedaNet様「WebViewを使ったアプリ作成その1
 
これはeclipseの利用バージョンの違いのためだと思います。私の利用している
eclipseのバージョンではレイアウトは以下の様に2種類あります。
layout
このうち「hello world」が設定されているのはfragment_main.xmlの方なのですが
こちらにwebViewを配置してもアプリが起動できません。
activity_main.xmlの方に配置すればOKです。
これはxcodeのストーリーボードのように複数の画面を扱うようになったから?
 

アプリの停止

xcodeではRUNボタンをクリックするとSTOPボタンになり、簡単にアプリを停止できる
のですがeclipsではSTOPボタンが分かりにくいところにありました。
以下のサイトが参考になりました。
→参考:日々の糧さま「android、eclipseでのデバッグ停止方法
 
以下がDDMSの画面で、ここで停止したいアプリを選択し(下図ではcom.example.hello)
上部のSTOPボタンをクリック。
stop
 

appcompat_v7の増殖

プロジェクトを作成する度に「appcompat_v7」が増殖していく…。
スクリーンショット 2014-04-13 17.23.41
この問題は以下のサイトで解決。
→参考:もぐら王国さま「“appcompat_v7″フォルダの自動作成ってバグなの?仕様なの
 
 
今回はここまで、次回はjQueryとAndroid間のデータのやり取りを学ぶ予定です。