SQLの窓

2017年11月18日


JavaScript から Android へアクセス

Android で、Google MAP を扱いたい場合、WebView 内で自分がホストしているページを扱うのがとても容易で便利です。しかし、そうした場合の一番の問題点は、WEBページと、Android とのデータのやり取りができないというところです。

しかし、Android 側の WebView の addJavascriptInterface メソッドでクラスを登録すると、そのクラスのメソッドが JavaScript から呼べるようになります。また、Android 側から JavaScript を呼び出す方法としても、WebView の loadUrl メソッドを使って loadUrl("javascript:コード") というように、ブックマークレットと同じ方法でアクセスできます。

Android の ドキュメントでは以下のようなコードが掲載されています( @JavascriptInterface に注意 / only public methods that are annotated with JavascriptInterface can be accessed from JavaScript )
class JsObject {
    @JavascriptInterface
    public String toString() { return "injectedObject"; }
 }
 webView.addJavascriptInterface(new JsObject(), "injectedObject");
 webView.loadData("", "text/html", null);
 webView.loadUrl("javascript:alert(injectedObject.toString())");
この例では、Android から Web ページの alert を呼び出して、その引数として Android 側のメソッドを与えています。結果的に、Android 側の "injectedObject" という文字列が、Webページ上の alert の結果として表示されます。
この内容は今もドキュメントにありますが、API level 19 から  evaluateJavascript が追加されています。こちらでは、JavaScript の戻り値を 非同期で UI スレッド上で得る事ができますので、こちらを使用したほうがいいでしょう。
以下はもう少し具体的なクラスを使った例、Webページ上のボタンで Android の intent を使用して画面遷移を行います。
package com.example.androidapp;

import android.content.Context;
import android.content.Intent;
import android.widget.Toast;

public class myWeb {
	Context mContext;

	myWeb(Context c) {
		mContext = c;
	}

	@JavascriptInterface
	public void showPostActivity(String message) {
		
		Intent intent = new Intent(mContext, PostActivity.class);
		intent.putExtra("message_text",message);
		
		// アクティビティの呼び出し
		mContext.startActivity(intent);
		
	}
}

このクラスを以下のようにして登録します
// ************************************************************
// WebView のイベントを処理する
// ************************************************************
webView = (WebView)findViewById(R.id.webView1);
webView.addJavascriptInterface(new myWeb(this), "MyWeb");
webView.setWebViewClient( new WebViewClient() {
		
		public boolean shouldOverrideUrlLoading(WebView view, String url) {
			Log.i("lightbox", url);
			return false;
		}

		// API level 24 以降ではこちら
		//public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request)
		//	Log.i("lightbox", url);
		//	return false;
		//}

	}
);		


最後にボタンで呼び出します( 緯度・経度を引き渡しています )
<input type="button" value="Android へアクセス" onclick="MyWeb.showPostActivity('-34.397, 150.644')">


関連する記事

WebView で JavaScript にデータを渡したい時に注意する事

Android で WebView を使ってWEBにあるデータベースのデータを取得する為のクラス



posted by lightbox at 2017-11-18 14:00 | Android | このブログの読者になる | 更新情報をチェックする

2015年04月19日


Monaca と 本当の 『Onsen UI最小限のテンプレート』



エクスポートしただけなので、インポートして使えます。



手元に Monaca 公式ガイドブックがあるのですが、インターネット上のドキュメントだけは情報が整理されていない上に一番キモとなるものは、検証しないと解らない事が多かったです。

とりあえず、ons-gesture-detector 要素の使い方のサンプルとして見て下さい。ちなみに、イベント内の gesture 情報を見るには通常 jQuery が必要です。jQuery mobile では、使えません。また、イベントの書き方としても、$(document).on('イベント', 'セレクタ', function(e){} でないと動作しませんでした。他の書き方で書いても、Monaca デバッガで動いても apk にビルドしたものは動作しませんでした。目安としては、プレビューで動かないものは、apk でも動かない可能性があります。

※ jQuery mobile は、コンソールのクリアがうまくいかないような気もします

index.html
<!DOCTYPE HTML>
<html>
<head>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
	<script src="components/loader.js"></script>
	<link rel="stylesheet" href="components/loader.css">
	<link rel="stylesheet" href="css/style.css">
	<script>
		ons.bootstrap();
		ons.ready(function(){
			console.clear();
			console.log("開始");

			$(document).on('click', '#gestureBtn', function(e){
				console.log("ページ移動\n------------");
				myNavigator.pushPage('page2.html');
			});

			// *************************************
			// gestureBtn 用
			// *************************************
			// タップ
			$(document).on('tap', '.gestureTest', function(e){
				console.log("tap");
				console.log("------------");
				for( prop in e.originalEvent.gesture) {
					console.log(prop);
				}
				
			});
			$(document).on('doubletap', '.gestureTest', function(e){
				console.log("doubletap");
			});

			// ホールド
			$(document).on('hold', '.gestureTest', function(e){
				console.log("hold");
			});
			$(document).on('release', '.gestureTest', function(e){
				console.log("release");
			});
			
			// ドラッグ
			$(document).on('drag', '.gestureTest', function(e){
				console.log("drag");
			});

			// その他
			$(document).on('touch', '.gestureTest', function(e){
				console.log("touch");
			});
			

			// *************************************
			// 共通
			// *************************************
			$(document).on('touchstart', '.gestureTest', function(e){
				console.log("touchstart");
			});

			$(document).on('touchend', '.gestureTest', function(e){
				console.log("touchend");
			});

		});
	</script>
</head>
<body>
	<ons-navigator var="myNavigator" page="page1.html">
	</ons-navigator> 
</body>
</html>


初期画面( page1.html )

ons-gesture-detector 内でのみ、スマホで必要ないろいろなイベントに対処できるようになっています。これを使わない場合は、touchstart と touchend とあといくつかの基本処理になります。ons-gesture-detector 内では、ここには無いもっと複雑なジェスチャー(スワイプ、ピンチ他)も対応されています。( 実機が無いので検証できませんでしたが )
<ons-page>
	<ons-toolbar>
		<div class="center">Navigator</div>
	</ons-toolbar>

	<div style="text-align: center">
		<br>
		<ons-gesture-detector>
		<ons-button
			class="gestureTest"
			id="gestureBtn">
			次のページを表示
		</ons-button>
		<br>
		(ジェスチャー対応)
		</ons-gesture-detector>
		
		<br>
		<ons-button
			class="gestureTest"
			onclick="myNavigator.pushPage('page2.html')"
			id="normalBtn">
			次のページを表示
		</ons-button>
		<br>
		(普通のボタン)
		
	</div>

</ons-page>


page2.html



<ons-page>
	<ons-toolbar>
		<div class="left"><ons-back-button>Back</ons-back-button></div>
		<div class="center">画像表示</div>
	</ons-toolbar>

	<div style="text-align: center">

		<h1>ページ&#10103;</h1>
		<ons-button
			onclick="myNavigator.popPage()">
		  Pop Page
		</ons-button>
		<br>
		<br>
		<img src="image/page2.jpg">

	</div>
</ons-page>


▼ 下の赤い枠内が gesture 情報



タグ:android MONACA
posted by lightbox at 2015-04-19 20:57 | Android | このブログの読者になる | 更新情報をチェックする

2015年03月29日


Android 5.1 リリース済み。SDK( android-sdk_r24.0.2-windows.zip ) でまずエミュレータ作って、あとから Eclipse と Android Studio で動作確認( 新しい事は、少しづつ問題を消して行くのが近道です )

重要

以下の理由で、エミュレータの RAM は 512 を推奨します
Android Studio : Intel の HAXM と System Image を最新にしたら、installation failed since the device possibly ... というエラーが出ました

Eclipse(Pleiades(Luna)+ADT Plugin)Android Studio の動作確認は終わってますが、ここではそれとは全く関係無い『エミュレータが動く』という事を目標に置いています。正直、最初のテストを古い PC でやってしまって結構いろんな壁にブチあたったりしてます。ですが、結果が重要なので実際に動作した AVD のバリエーションを掲載します。

いずれにしても Java は必要

後の Eclipse や Android Studio を考えたとしても、最近では Java そのものをあまり意識する必要は無いようになって来ていますが、とりあえず Java のアプリケーションが動く環境が必要です。

SDK Manager.exe を起動して、めぼしいバージョンを更新

Android 4.1.2 〜 Android 5.1 の 更新です。結構かかります。ま、でも Android 5.1 だけ入れておいて必要に応じて増やせばいいと思います。









Extras は、とにかく全部入れました(全部必要では無いはずですが、確認取る時間がもったいないので全部入れています)。ただ、最後のアクセラレータはとても重要です。

CPU のオプションとして Windows では通常オフになっていると思いますが、BIOS の設定でオンにした上でインストールするドライバが ectras フォルダに展開されます。インストールは、その中の intelhaxm-android.exe を実行する事によって、アンインストール可能な公式のインストール一覧(プログラムと機能)に表示される形でインストールされます。インストールされると、表からは見えない形のサービスとして起動されて、AVD の x86 関係の CPU が利用できるようになります。

▼ インストール後確認できるレジストリ位置
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\IntelHaxm
( サービス名を使用して、sc query IntelHaxm で確認する事もできます )



type が 1 とあるのは、Kernel device driver である事を示しています

AVD Manager.exe を起動して、デバイスを作成

Nexus S の情報を元にして作成しています



6つのバリエーションを作成して、起動を確認した後に設定アイコンで日本語に変更しています。

これらの設定情報は、C:\Users\ユーザ名\.android\avd に作成されており、この名前とこの中にある .ini ファイル名前を変更して、AVD Manager.exe で読み出した後に更新すると名称変更が可能である事を確認しました。




AVD_for_Nexus_S_412x86



AVD_for_Nexus_S_442x86



AVD_for_Nexus_S_by_Google


Google APIs 関連はなぜか警告が出ますが、間違った内容の警告が出されておりきちんと動作します。

AVD_for_Nexus_S_TEST1



AVD_for_Nexus_S_TEST2



AVD_for_Nexus_S_TEST3



優先順位としては、Android 5.1 で動作確認するといいと思いますが、Android 4.1.2 もそれなりに重要な気もします。Google APIs は、Google 特有のサービスをテストする際に必要だという事が調べた結果なのですが、ここは確認していません。というか、普通の Android アプリケーションを実行するだけなら、Google APIs は必要無いでしょう。armeabi-v7a があるのは、古い PC では アクセラレータを実行する為の機能そのものが無いのでその場合に必要になります( エミュレータの起動は遅くなりますがしかたありません )


以上全ての動作を確認しています

Android 5.0 以降のオープニングは、一番下にあるロックをゆっくり上へドラッグして中に入ります。




関連する記事

Android 5.1 エミュレータ + Android Studio 1.1.0 実行イメージ


Android 5.1 + Pleiades( Luna ) + ADT Plugin


Android Studio と Pleiades Eclipse + Android SDK が参照する Java SE ドキュメントを日本語化する


Android Studio のインストールとエミュレータ実行までの手順




タグ:android
posted by lightbox at 2015-03-29 16:48 | Android | このブログの読者になる | 更新情報をチェックする

2015年03月28日


クラウドでアプリを作成してスマホで動作させる『Monaca』を Android エミュレータの 5.1 で動作確認しました

Monaca は、オンラインで HTML5 と JavaScript を使ってプログラムを書いて、Android または iOS のアプリ経由で実行させるサービスです。実際のアプリとしてビルドも可能ですが、フリーだと24時間に3回だけビルドできるという制限があります。が、開発だけならフリーでも十分です。実際 Android エミュレータ内で普通に動いています。

Monaca の運営会社はアシアル株式会社という日本のベンチャー企業です。ですから、全て日本語で情報が手に入ります。ライセンスの問い合わせも簡単に確認できるはずです。



エミュレータを使うにはいろいろありますが、一番の問題は 公式の apk では 実際問題動作しない事です。

そもそも、更新が 2012年12月19日 で止まっており。公式ページの方法でインストールできるのが Android 4.2.2 までです。それ以降でインストールができないのは、Android のセキュリティ上の問題でしょうが、adb install でインストール可能です( 削除はエミュレータ内のアプリの管理から削除できます )

しかし、仮にインストールしたとしても『ある事』をしないと落ちます。結局最新の apk を apk ダウンローダで入手して adb install するのが推奨されますが、公式にはそんな事できるはずも無いので放置されているみたいです。

『ある事とは』



この行を削除すると、古い apk でも動作しました。何故これが解ったかというと、エミュレータを Android Studio で動作させながらログを監視すると、この行が原因と思われるエラーが出たからです。

最新を使ったほうが・・・

いいのは決まっています。今回動いたからといっていつ動かなくなるか解りませんし、最新のほうが機能が豊富です。但し、Android エミュレータで動かすには公式のサポートは望めないでしょう。しかし、エミュレータで動作する事は、実機を用意しなくていいのでとても魅力的です。





▼ 画像を掲載しやすいので、NAVER でまとめました。
Android エミュレータで使う Monacaデバッガー の選択肢


エミュレータ環境もそれなりに面倒です

非力または古い PC ですといろいろ制限がありました。

armeabi-v7a しか動かない、ちょっと古い PC で、どーしてもエミュレータが起動しなくてやった事

関連する記事

SDK( android-sdk_r24.0.2-windows.zip ) でまずエミュレータ作って、あとから Eclipse と Android Studio で動作確認
Android 5.1 エミュレータ + Android Studio 1.1.0 実行イメージ
Android 5.1 + Pleiades( Luna ) + ADT Plugin




タグ:android MONACA
posted by lightbox at 2015-03-28 01:04 | Android | このブログの読者になる | 更新情報をチェックする

2013年10月29日


Android で Post と Get

HashMap を使って以下のように使用します

Map map = new HashMap();
map.put("url", "");
map.put("charset", "SHIFT_JIS");
map.put("action", "regist");
map.put("name", "lightbox");
map.put("title", "日本語");
map.put("comment", "本文");

new HttpPost() {
	@Override
	protected void onPostExecute(String result) {
		System.out.println(result);
	}
}.execute(map);

HttpPost.java
package jp.winofsql;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Iterator;
import java.util.Map;

import android.os.AsyncTask;
import android.util.Log;

// *********************************************************
// POST して テキストを取得する
// *********************************************************
public class HttpPost extends AsyncTask<Map, Void, String> {

	@Override
	protected String doInBackground(Map... params) {
		
		StringBuffer get_data = null;
		
		Map<String,String> myArg = params[0];

		try {
			// ターゲット
			URL url = new URL(myArg.get("url"));
			// 接続オブジェクト
			HttpURLConnection http = (HttpURLConnection)url.openConnection();
			http.setConnectTimeout(30000);
			http.setReadTimeout(30000);
			http.setDoOutput(true);
			http.setRequestMethod("POST");
			// 接続
			http.connect();
			
			OutputStreamWriter osw = new OutputStreamWriter(http.getOutputStream());
			BufferedWriter bw = new BufferedWriter(osw);
			
			Iterator<String> it =  myArg.keySet().iterator();
			String key = null;
			String value = null;
			String data = "";
			while(it.hasNext()) {
				key = it.next().toString();
				if ( key.equals("url") ) {
					continue;
				}
				value = myArg.get(key);
				if ( !data.equals("") ) {
					data += "&";
				}
				data += key + "=" + URLEncoder.encode(value, myArg.get("charset")) ;
			}
			
			Log.i("",data);
				
			bw.write( data );

			bw.close();
			osw.close();
			
			// 以下読み込み3セット
			InputStream i_stream = http.getInputStream();
			// UTF-8 でリーダーを作成
			InputStreamReader i_stream_reader = new InputStreamReader(i_stream, myArg.get("charset"));
			// 行単位で読み込む為の準備   
			BufferedReader b_reader = new BufferedReader(i_stream_reader);
			
			// 行の一括読みこみ
			String line_buffer;
			get_data = new StringBuffer();
			// BufferedReader は、readLine が null を返すと読み込み終了 
			while ( null != (line_buffer = b_reader.readLine() ) ) {   
				// コマンドプロンプトに表示   
				get_data.append( line_buffer );
				get_data.append( "\n" );
			}
			
			// 接続解除
			http.disconnect();
		}
		catch(Exception e) {
			Log.i("HttpPost", e.getMessage());
		}
		return get_data.toString();
	}
	

}

Get は 実行時の引数に URL と キャラクタセットを指定します

new HttpGet() {
	@Override
	protected void onPostExecute(String result) {
		System.out.println(result);
	}
}.execute("http://matome.naver.jp/feed/hot","UTF-8");

HttpGet.java
package jp.winofsql;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

import android.os.AsyncTask;
import android.util.Log;

// *********************************************************
// GET して テキストを取得する
// *********************************************************
public class HttpGet extends AsyncTask<String, Void, String> {

	@Override
	protected String doInBackground(String... params) {
		StringBuffer get_data = null;

		try {
			// ターゲット
			URL url = new URL(params[0]);
			// 接続オブジェクト
			HttpURLConnection http = (HttpURLConnection)url.openConnection();
			// GET メソッド
			http.setRequestMethod("GET");
			// 接続
			http.connect();

			
			// 以下読み込み3セット
			InputStream i_stream = http.getInputStream();
			// UTF-8 でリーダーを作成
			InputStreamReader i_stream_reader = new InputStreamReader(i_stream, params[1]);
			// 行単位で読み込む為の準備   
			BufferedReader b_reader = new BufferedReader(i_stream_reader);
			
			// 行の一括読みこみ
			String line_buffer;
			get_data = new StringBuffer();
			// BufferedReader は、readLine が null を返すと読み込み終了 
			while ( null != (line_buffer = b_reader.readLine() ) ) {   
				// コマンドプロンプトに表示   
				get_data.append( line_buffer );
				get_data.append( "\n" );
			}
			
			// 接続解除
			http.disconnect();					
		}
		catch(Exception e) {
			Log.i("HttpGet", e.getMessage());
		}						
		return get_data.toString();	
	}

}
関連する記事

Framework4.5(C#)ストア : HttpClient で Post と Get する汎用 static クラス
Framework4(C#) : WebClient で Post と Get する汎用 static クラス
Framework4(C#) : Windows Phone OS 7.1 : WebClient で Post と Get する汎用 static クラス



posted by lightbox at 2013-10-29 21:37 | Android | このブログの読者になる | 更新情報をチェックする

別の ADT(Android) で作成されたワークスペースを最新の ADT で開く場合の操作方法

現在の状態



現在最新の ADT では、以前必要だった空のプロジェクトを作成せずにインポートできますが、Metadata が含まれたワークスペースを開く場合は、SDK の場所の変更と、プロジェクトが使用する Android SDK のバージーョンを指定する必要がある場合があります。

まず、プロジェクトが『自動にビルド』になっている事を確認



SDK の場所の再設定







プロジェクトの SDK のバージョンの選択






これ以外にも、直接動作に支障が無い場合が多いですが、Manifest に SDK のターゲットを指定する場所があります。 



posted by lightbox at 2013-10-29 13:13 | Android | このブログの読者になる | 更新情報をチェックする
Seesaa の各ページの表示について
Seesaa の 記事がたまに全く表示されない場合があります。その場合は、設定> 詳細設定> ブログ設定 で 最新の情報に更新の『実行ボタン』で記事やアーカイブが最新にビルドされます。

Seesaa のページで、アーカイブとタグページは要注意です。タグページはコンテンツが全く無い状態になりますし、アーカイブページも歯抜けページはコンテンツが存在しないのにページが表示されてしまいます。

また、カテゴリページもそういう意味では完全ではありません。『カテゴリID-番号』というフォーマットで表示されるページですが、実際存在するより大きな番号でも表示されてしまいます。

※ インデックスページのみ、実際の記事数を超えたページを指定しても最後のページが表示されるようです

対処としては、このようなヘルプ的な情報を固定でページの最後に表示するようにするといいでしょう。具体的には、メインの記事コンテンツの下に『自由形式』を追加し、アーカイブとカテゴリページでのみ表示するように設定し、コンテンツを用意するといいと思います。


※ エキスパートモードで表示しています

アーカイブとカテゴリページはこのように簡単に設定できますが、タグページは HTML 設定を直接変更して、以下の『タグページでのみ表示される内容』の記述方法で設定する必要があります

<% if:page_name eq 'archive' -%>
アーカイブページでのみ表示される内容
<% /if %>

<% if:page_name eq 'category' -%>
カテゴリページでのみ表示される内容
<% /if %>

<% if:page_name eq 'tag' -%>
タグページでのみ表示される内容
<% /if %>
この記述は、以下の場所で使用します
container 終わり

フリーフォントで簡単ロゴ作成
フリーフォントでボタン素材作成
フリーフォントで吹き出し画像作成
フリーフォントではんこ画像作成
ほぼ自由に利用できるフリーフォント
フリーフォントの書体見本とサンプル
画像を大きく見る為のウインドウを開くボタンの作成

CSS ドロップシャドウの参考デモ
BUTTONS (CSS でボタン)
イラストAC
ぱくたそ
写真素材 足成
フリーフォント一覧
utf8 文字ツール
右サイド 終わり
base 終わり