2011年12月8日木曜日

N700系第2弾

先月に続いて大阪へ出張へ行って来ました。
いつものようにN700系を利用しましたので、無線LANの報告を・・・

行きはやはりmobilepointは接続することはできませんでした。朝でビジネスマンの利用が多いこともあってか、docomoの方も接続ができない時もありましたが、概ね問題なく利用することができました。ソフトバンクが無線LANへの接続を促しているので、無線LANの利用者が多くなっているのも原因かもしれません。

帰りについては、mobilepointも問題なく接続することができました。
列車によるのでしょうか?

通信速度については、docomoも同じようなレベルでしたが、多少画像があるページぐらいでしたら、ちょっと待てば表示されるのでそれほどのストレスを感じることはありませんでした。

2011年11月16日水曜日

N700系無線LAN

大阪へ出張に行ってきました。

大阪への出張の場合、というか新幹線を利用する場合はできるだけN700系を利用するようにしています。
壁際に電源コンセントがあるのも便利ですが、無線LANが使えるのが一番のポイントです。
今回もwRecX(Pro)のテストを兼ねて無線LANを利用しましたが、その結果の報告です。

N700系内ではドコモとBBモバイルが利用可能です。(東京←→新大阪間限定?)

どちらも契約をしているので、両方試してみましたが、ドコモは問題なく接続できましたが、BBモバイルはネットワークの遅延が発生していてまったく使い物になりませんでした。

どちらも無線強度は十分なのですが、接続後のネットワークバックボーンの問題なのでしょうか、BBモバイルに切り替えるとステータスのWi-Fiマークに黄色いびっくりマークが表示されて接続することができませんでした。ネットワークツールでpingを打ってみましたが、どうやらDNSの名前解決でエラーになっているようです。直後にドコモに切り替えると問題無く接続できましたから、やはりBBモバイルの問題なのでしょう。

似たような現象として、マクドナルドで接続をしていると突然接続が切れるという現象が発生しました。ログインまでは問題なくできて、サイトを見ていて、別のサイトに飛ぼうとすると、ログイン画面が表示されることが何度も発生しました。
多少電波は弱くてもドコモに切り替えると、スピードは遅いながら接続が切れるようなことが無いので、ストレスが少なくてすみます。

ドコモもまだiPhoneの交渉を継続しているようですが、ドコモからiPhoneが出たら・・・

いづれにしろ、キャリアをソフトバンクに切り替えることは絶対に無いと思わせてくれた今回の出張でした。

2011年11月5日土曜日

外部データベースとログイン設定

時間がかりましたが、アクセスポイントの外部データベースが作成できましたが、ブログへは画像しかアップできないんですね。

どうやら、Google Docsにならアップできるようなので、試してみることにしました。

1.docomo+mobilepointは こちら

2.docomoは こちら

3.mobilepointは こちら

になります。圧縮してありますので、解凍後、スマートフォンの/sdcard/jp.gr.tokotoko/data/にコピーしてください。

注)
従来からご利用いただいている方は/sdcard/media/data/へコピーしてください。
/sdcard/mediaについてはXPERIAで利用されている事、デベロッパー毎に判りやすいフォルダを利用した方がユーザ様にとってもSDカードの管理が判りやすいとの判断から、今後順次移行して行く予定です。(2011/11/10追記)

また、各プロバイダのLogin設定については以下の設定を参考にしていただけれえばと思います。

◆ docomoの設定


URLとActionは何も設定していません。methodはPOSTです。
◆ mobilepointの設定

◆ livedoor-webの設定

2011年10月31日月曜日

Google Maps API有料化の詳細発表でわさわさし始めていますが

GPS機能を使ったアプリを開発している者としては、気になる発表ですが・・・

ウエブサイトでで利用している場合は、発表の通り受け止めれば良いのでしょうが、アプリ開発者としてはそのまま受け取って良いのかが疑問です。

例えば、私が利用しているジオコーディングAPIでは2,500リクエスト/日が上限となっています。(毎秒5件も別要件でありますが)
GPSの位置情報から、場所(住所)を求めていたりすると、数回のリクエストで済みますが、アプリが1000本ぐらいダウンロードされていたら、どうなるんでしょうかね?
ダウンロードされたアプリが全て1日に数回利用されると、すぐにこの上限は上回ってしまします。

Modify your Maps API application such that the number of map loads generated per day is below the usage limit for each API that your application uses;

拙い英語力でこれの意味を取ると、Maps APIを利用するアプリケーションが1日の利用制限を越えなけらば良い、とはアプリケーションの1本1本が、という風にとれます。

しかしながら、アプリ単位に集計するなら、MapViewに記述されたKeyで集計すれば簡単ですが、個人毎に集計する為には、アプリケーションを利用した時に、端末固有情報(IPアドレス?)も併せて収集する必要があると思います。
さらに、複数のアプリでMap APIが利用されている場合の、APIカウントの方法は?

なんか、このあたりが不明瞭なまま、有料化の話だけがうろうろしているようです。


◆追跡アプリケーションでの Google Maps API の使用
アプリケーションが無料で開放されているか、利用規約に準拠していれば、Google Maps API を使用したリアルタイム データ(追跡)の表示に制約はありません。内部的にのみ使用されるアプリケーションの場合には、Google Maps API Premier を使用しなければなりません。詳細は、利用規約のセクション 10.9 をご覧ください。

というエントリが「Google Maps API ファミリー」のFAQに出ていました。

これからすると、無料か、利用規約に準拠していれば、課金は無いのかな?・・・でも、無料サイトならOKみたいな記述もあるので、この規約も変更されるのかな?

内部的にとは、社内利用のようです。


さらにFAQの下の方では

◆送信できるジオコード リクエスト数の制限
1 つの IP アドレスから 24 時間以内に送信されるジオコード リクエストが 2,500 件を超える場合や、1 つの IP アドレスから送信されるジオコード リクエストの頻度が高すぎる場合、Google Maps API ジオコーダはステータス コード 620 で応答するようになります。この記事では、PHP からのジオコード リクエストの調節方法の説明と、その場合のサンプル コードを示しています。ジオコーダの過度の使用が続く場合、この IP アドレスからの Google Maps API ジオコーダは永久にブロックされる場合があります。
Maps API ジオコーディング クラスのいずれかを使用する場合、リクエストはユーザーのウェブブラウザから行われ、回数制限はそのユーザーの IP アドレスに対する割り当てに基づいて課せられます。

アプリケーションへの課金で妥当なところは、「Maps API Key + IPアドレス」毎に2,500 件/日を超える場合、Maps API Keyに課金?

でも、これでも開発者サイドとしては、課金されるリスクがあるのでやっぱりMaps APIを利用したアプリの開発からは手を引きたくなるでしょうね。
さらに、すでに流通しているアプリについてはどうするのか?Googleのことだから、あまり考えていそうにないのが怖いですね。

こんな、金儲けのことばかり考えていないでまずは不安定なマーケットを安定してもらわないと、開発者も嫌気がさしてくると思いますが、いかがでしょうかね?

様子を見て、年内には私もどうするか決めたいと思いますが、いまのままの状態なら、Maps API利用アプリは全て非公開とするしかなさそうです。

wRecX(Pro)最新バージョンをリリースしました。

バージョン4.3.0として先ほどリリースしました。

それにしてもGoogleさんにはいつもながら泣かされます。
マーケットの機能をもう少しまともにしてほしいですね。
今回、wRecXDroidも同時に新バージョンをリリースしましたが、証明書の切替を行ったところ、今までのアプリケーションとしてはバージョンアップがでlきませんでした。同じ証明書でないと同一アプリとは認めてくれないようです。仕方が無いので、従来のアプリについては廃版として新しいアプリケーションとしてリリースいたしました。

廃止したアプリが削除できないなど、もう少し開発サイドのことも考えてもらいたいものです。


さて、次は来年に向けて、サービス化とウイジットのサポートを考えています。

現在、5つのプロジェクトを抱えているので果たしてお正月までに間に合うか?桜の便りが聞こえてきたなんてことにならないように頑張りたいと思います。

2011年10月28日金曜日

ログイン処理の不具合

現在、何らかの原因でログイン処理に失敗すると、ログインできなくなるという不具合が発生しております。
wRecXを一旦強制終了させた後、再起動すると正常にログインできるようになります。
現在、原因を調査中ですが、どうやらHTTP処理関連のオブジェクトを使いまわしているのが原因のようです。HT-03Aといういまではだいぶ非力な端末を利用していた為、できるだけ処理を軽くするためでしたが、それがいけなかったようです。
現在、修正版のフィールドテストを行っているので、数日中にバージョンアップしたいと思います。

それまでの間は、ご不便ですがログイン処理に失敗した場合はwRecXを一旦強制終了させていただきますようお願いいたします。


同時にPro版もリリースできそうです。

2011年10月24日月曜日

APNDroidが有料になったようです!

今週の土曜日に携帯を機種変更してきました。
さすがにHT-03Aでは非力すぎて、画面切替でブルー画面(背景が標準の湖に設定していたもので)となることがしばしばでした。
やっと、人並みに使えるようになりそうです。

さて、自宅に帰って設定をと思ったところ今で愛用していたAPNDroidの無料版が無くなっているようです。

古い携帯から.apkファイルを抜き出してインストールしてもいいのですが、それならいっそwRecXをバージョンアップしてしまえということで、突貫工事でバージョンアップを行いました。
APNDroidと同じ機能としても良かったのですが、同じ事をしても仕方がないので、APNを切り替えるという機能にしました。

使い方としては

1.ダミーのAPNを登録してください。

設定→無線とネットワーク→モバイルネットワーク→アクセスポイント名で「MENUキー」を押して、新しいAPNで追加できます。
名前とAPN名だけで大丈夫です。

2.wRecX(Free)の設定画面でAPNの切替を設定します。

・ONのときのAPNに通常使用しているAPNを指定してください。先ほどのAPN追加の時に、通常使用しているAPNをコピーしておくと楽でしょう。
・OFFの時のAPNに先ほど追加したAPNを指定します。
・wRecX(Free)を再起動してください。

以上で設定は終わりです。

APNDroidがインストールされていても、この設定を優先します。
自分はdocomoのmopera契約なので、その他の環境で動作するかは確認できていませんが(特にdocomoのspモードはテザリングの関係もあってだいぶ手を入れているようです)うまく動作しない場合は、上記設定をクリアすることで、APNDroidを利用することも可能です。
私のテストした範囲では、安定して動作しています。反応もAPNDroidよりも早いようです。
電源OFF後も設定は問題ありませんでした。


現在Pro版の最終テストを行っていますが、なんとか今月中にはリリースしたいと思います。
問題は、docomoとmobalipointのアクセスポイントデータベースの作成ですが、場合によってはデータベースのリリースだけ別途としたいと思います。

2011年10月13日木曜日

GPS機能と外部データベース

現在、更新が滞っていますが時間が取れたら外部データベースのメンテナンスを行いたいと思います。(年内にはできるかな)

さて、GPS機能ですが

GPS機能をONにすると、こんな画面になります。


検索アイコンをクリックすると、外部データベースの検索が可能となります。(外部データベースがないとだめですが)
現在位置から指定半径に存在するアクセスポイントを検索します。
検索結果が一覧で表示されます。
目的の場所を長押しすると、こんなメニューが出てきます。
ネットワークに接続している場合が、Google Mapでの経路検索も可能です。
ネットワークに接続していない場合は、コンパスを頼りに目的地を目指します。

2011年10月12日水曜日

wRecX(Pro) 4.0.0

いままで、日本向けにのみ公開していましたが、制限を解除することにしました。
合わせて、いくつかの機能追加を行いましたので、ここで整理しておきたいと思います。
なお、Pro版の公開はFree版を公開してから1ヶ月後を予定しています。Free版が安定しているようでしたら公開を早めるかもしれません。

以下がPro版で追加してある機能です。

◆GPS機能
・登録されたアクセスポイント(AP)に近付くと自動的に接続先を切り替えAPの自動スキャンを行います。
・登録されたAPや場所を方向(コンパス)と距離で指示します。
・ネットワークに接続可能な場合、Mapsで目的地までの経路を表示します。

◆ネットワークツール(Ver.4.0.0で追加)


・ping / netstat / ls / cat コマンドの実行が可能です。
・BusyBoxがインストールされている場合、さらに arp / ip / nslookup / route / traceroute の実行が可能となります。
◆WIfiConfigurationの保存機能(Ver.4.0.0で追加)
Free版ではパスワードなどの情報は一度登録すると、内容を確認することができませんが、wRecX(Pro)の場合は本アプリケーションで入力した内容はすべてローカルデータベースに保存する為、内容の変更が可能となります。

◆アプリケーションランチャ
「現在の接続」表示エリアで右から左へスワイプすることでアプリケーション画面を表示します。


・最大16個のアプリケーションを登録可能(長押しで設定ダイアログを表示)
・ネットワークに接続していない時、3Gに接続してからアプリケーションを起動(アプリケーション毎にこの機能を強制的に無効に設定することも可能)
◆外部データベース
別提供のwRecXDroidを使用して、アクセスポイント等の位置情報データベースの作成を行うことで、GPS機能がONで位置情報が取得されている時に、この外部データベースの検索を行うことが可能となります。予め、プロバイダの提供するアクセスポイント一覧を取り込んでおくことによって、外出時にアクセスポイントをネットワークに接続していない状態でも検索することが可能となります。

2011年9月23日金曜日

Login機能

プロバイダへログインする機能です。

前提条件:

WiFi接続設定が完了していること。

設定方法:
  1. WIFiの有効範囲へ移動してください。

  2. WIFiの接続が完了したことを確認してください。

  3. wRecXのメニューからネットワークを選択して、該当のSSIDを長押ししてください。

  4. 表示されたリストからログインの設定を選択してください。

  5. Login:
    アクセスポイントに接続した時、自動的にログインを行う(Auto)のか、手動(Manual)で行うのかを選択します。

    URL:
    ログイン用URLを指定します。通常のプロバイダの場合は指定する必要はありません。

    Action:
    formのactionを指定します。通常のプロバイダの場合は指定する必要はありません。

    Method:
    formのmethodを指定します。

    Element:
    ログイン用Formに送信する項目を設定します。(ログイン解析機能で項目の抽出が可能です)

  6. Elementの編集

  7. name:
    formの入力項目名を指定します。

    value:
    formの入力項目の値を指定します。

    password:
    value項目をパスワードとして表示します。

    hidden:
    ログイン解析機能で設定されるだけで、ログイン処理では使用していません。







  8. メニューの説明

  9. 保存:
    設定した内容をローカルデータベースに保存します。バックキーでは保存しないので注意してください。

    Formを隠す:
    Form項目を隠して、Element用表示エリアを確保します。

    Elementを追加:
    Elementを追加します。

    ログインのテスト:
    設定した内容でログインを行います。

    ログイン解析:
    ログイン用画面にアクセスして、Form及びInput項目をHTMLから解析します。


  10. ログイン解析機能について
  11. あらかじめログイン用のURL、入力項目等がわかっていれば良いのですが、一般的なプロバイダの場合はログイン用情報は公開されていないことが多いようです。(HTMLを見れば全て判るので、公開されていないというのは正確ではありませんが、ドキュメントとしてホームページ等には公開はされていないようです。)そこで、ログイン用画面を取得して、そのHTMLからForm情報と入力項目を解析する機能です。

    以下の手順でログイン画面の解析を行います
    1. ログイン用画面へのアクセス
    2. ログインの設定画面で「URL」が指定されている場合はそのURLへ、指定されていない場合はwRecXの設定画面の「Login/ログインチェック用ホスト」からURLを作成しWebViewを使用して画面を取得します。
    3. リダイレクト等の処理
    4. 要求へのレスポンスがリダイレクトされる場合は、WebViewが処理を自動的に行います。
    5. フォーム情報の取得
    6. 最終的に取得されたレスポンスからJavaScriptを使用してForm情報とElement情報を取得してダイアログに表示します。
    7. フォーム情報の保存
    8. ダイアログの保存ボタンが押された場合、Form情報とElement情報をログイン設定画面に反映させます。

  12. ログインテスト機能について
  13. 設定されているForm情報、Element情報にしたがってログイン情報をホストに送信し、実際にログインを試みます。
    1. URLが指定されている場合
    2. URL、Action、Elementに従って、指定されたMethodでホストにデータを送信します。
    3. URLが指定されていない場合
      • wRecXの設定画面の「Login/ログインチェック用ホスト」へのGET要求を行います。
      • レスポンスがリダイレクトまたはリフレッシュの場合は、指定されたURLへ再度GET要求を行います。
      • レスポンスがリダイレクトまたはリフレッシュ以外になるまで、要求を繰り返します。
      • レスポンスを解析してForm、Action、Elementを取得し、設定されている項目をマージします。
      • Form、Action、Elementから作成した要求をホストへ送信します。この時、レスポンスのFormにMethodの指定があれば、指定されたMethodで、指定がなければログインの設定で指定されたMethodを使って要求を送信します。

  14. Actionのオプション指示について
  15. Actionに「@noadjust」と指示された場合、ログイン画面のHTMLを解析したFormで指示されているactionを無視して、ログイン要求を作成します。
    通常はFormのactionでデータの送信先が指示されているので、ログイン画面のFormの送信先URLはログイン画面のURLからファイル名(URLの最後の要素)を除き、actionで指示された送信先を連結したものとなりますが、ログイン画面のURLへ再度要求を送信する必要のあるプロバイダがあるようです。(libidoor-webへのログインテスト中に判明)

    通常のブラウザでログインする場合はどのように処理されているのか不明ですが、libidoor-webについては、とりあえずこのオプションでログインできるようになりました。

2011年9月19日月曜日

MyWifiConfiguration

WifiConfigurationの全項目をハンドリングしやすくするため作成したクラスです。
コンストラクタでWifiConfiguration を取り込み、getで設定した値を反映したWifiConfiguration が取得できます。
修正にあたっては、現在ではほとんど利用されていないでしょうがAndroid1.6にも対応しました。(自分が使っているAndroidが1.6なもので)

UI関連やデータの保存については各自プログラムしてください。


/* Copyright 2010 OddRain
 * Copyright 2010 marcus905 
 * Copyright 2011 koichirosa10 
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

/* modifyed 2011, koichirosa10@gmail.com
 *
 *  -  It class-ized.
 *  -  It corrected so that it might operate by Android1.6.
 *  -  The code for CM6 was deleted.
 *
 */
package jp.hoge;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.BitSet;

import android.net.wifi.WifiConfiguration;

public class MyWifiConfiguration implements Serializable {
	private static final long serialVersionUID = 1554241197910887802L;

	private static final String INT_PRIVATE_KEY = "private_key";
	private static final String INT_PHASE2 = "phase2";
	private static final String INT_PASSWORD = "password";
	private static final String INT_IDENTITY = "identity";
	private static final String INT_EAP = "eap";
	private static final String INT_CLIENT_CERT = "client_cert";
	private static final String INT_CA_CERT = "ca_cert";
	private static final String INT_ANONYMOUS_IDENTITY = "anonymous_identity";

	private static final String INT16_PRIVATE_KEY = "privateKey";
	private static final String INT16_PRIVATE_KEY_PASSWORD = "privateKeyPasswd";
	private static final String INT16_PHASE2 = "phase2";
	private static final String INT16_PASSWORD = "password";
	private static final String INT16_IDENTITY = "identity";
	private static final String INT16_EAP = "eap";
	private static final String INT16_CLIENT_CERT = "clientCert";
	private static final String INT16_CA_CERT = "caCert";
	private static final String INT16_ANONYMOUS_IDENTITY = "anonymousIdentity";

	private static final String INT_ENTERPRISEFIELD_NAME = "android.net.wifi.WifiConfiguration$EnterpriseField";
	protected static final int SHOW_PREFERENCES = 0;

	public int networkId;
    public int status;
    public String SSID;
    public String BSSID;
    public String preSharedKey;
    public String[] wepKeys;
    public int wepTxKeyIndex;
    public int priority;
    public boolean hiddenSSID;

    public BitSet allowedKeyManagement;
    public BitSet allowedProtocols;
    public BitSet allowedAuthAlgorithms;
    public BitSet allowedPairwiseCiphers;
    public BitSet allowedGroupCiphers;

    public String eap;
    public String phase2;
    public String identity;
    public String anonymous_identity;
    public String password;
    public String client_cert;
    public String private_key;
    public String ca_cert;

    public MyWifiConfiguration() {
    	allowedKeyManagement = new BitSet();
    	allowedProtocols = new BitSet();
    	allowedAuthAlgorithms = new BitSet();
    	allowedPairwiseCiphers = new BitSet();
    	allowedGroupCiphers = new BitSet();
    	wepKeys = new String[4];
    }
    public MyWifiConfiguration(WifiConfiguration conf) throws Exception {
        networkId = conf.networkId;
        status = conf.status;
        SSID = MyWifiTools.removeQuotes(conf.SSID);
        BSSID = conf.BSSID;
        String val = MyWifiTools.removeQuotes(conf.preSharedKey);
        preSharedKey = ((val == null || val.equals("*")) ? null : val);
        wepKeys = new String[conf.wepKeys.length];
        for (int j = 0; j < wepKeys.length; j++) {
            wepKeys[j] = ((conf.wepKeys[j] == null || conf.wepKeys[j].equals("*")) ? null : MyWifiTools.removeQuotes(conf.wepKeys[j]));
        }
        wepTxKeyIndex = conf.wepTxKeyIndex;
        priority = conf.priority;
        hiddenSSID = conf.hiddenSSID;

        allowedKeyManagement = conf.allowedKeyManagement;
        allowedProtocols = conf.allowedProtocols;
        allowedAuthAlgorithms = conf.allowedAuthAlgorithms;
        allowedPairwiseCiphers = conf.allowedPairwiseCiphers;
        allowedGroupCiphers = conf.allowedGroupCiphers;

		setEnterprisefield(conf);
    }
	private void setEnterprisefield(WifiConfiguration conf) throws Exception {
		Class[] wcClasses = WifiConfiguration.class.getClasses();
		Class wcEnterpriseField = null;
		for (Class wcClass : wcClasses)
			if (wcClass.getName().equals(INT_ENTERPRISEFIELD_NAME)) {
				wcEnterpriseField = wcClass;
				break;
			}
		boolean noEnterpriseFieldType = false;
		if(wcEnterpriseField == null)
			noEnterpriseFieldType = true;

		// EnterpriseField
		Field wcefAnonymousId = null;
		Field wcefCaCert = null;
		Field wcefClientCert = null;
		Field  wcefEap = null;
		Field  wcefIdentity = null;
		Field  wcefPassword = null;
		Field  wcefPhase2 = null;
		Field  wcefPrivateKey = null;
		@SuppressWarnings("unused")
		Field  wcefPrivateKeyPassword = null;

		Field[] wcefFields = WifiConfiguration.class.getFields();
		for (Field wcefField : wcefFields) {
			if (wcefField.getName().trim().equals(INT_ANONYMOUS_IDENTITY))
				wcefAnonymousId = wcefField;
			else if (wcefField.getName().trim().equals(INT_CA_CERT))
				wcefCaCert = wcefField;
			else if (wcefField.getName().trim().equals(INT_CLIENT_CERT))
				wcefClientCert = wcefField;
			else if (wcefField.getName().trim().equals(INT_EAP))
				wcefEap = wcefField;
			else if (wcefField.getName().trim().equals(INT_IDENTITY))
				wcefIdentity = wcefField;
			else if (wcefField.getName().trim().equals(INT_PASSWORD))
				wcefPassword = wcefField;
			else if (wcefField.getName().trim().equals(INT_PHASE2))
				wcefPhase2 = wcefField;
			else if (wcefField.getName().trim().equals(INT_PRIVATE_KEY))
				wcefPrivateKey = wcefField;

			// for Android1.6
			else if (wcefField.getName().trim().equals(INT16_ANONYMOUS_IDENTITY))
				wcefAnonymousId = wcefField;
			else if (wcefField.getName().trim().equals(INT16_CA_CERT))
				wcefCaCert = wcefField;
			else if (wcefField.getName().trim().equals(INT16_CLIENT_CERT))
				wcefClientCert = wcefField;
			else if (wcefField.getName().trim().equals(INT16_EAP))
				wcefEap = wcefField;
			else if (wcefField.getName().trim().equals(INT16_IDENTITY))
				wcefIdentity = wcefField;
			else if (wcefField.getName().trim().equals(INT16_PASSWORD))
				wcefPassword = wcefField;
			else if (wcefField.getName().trim().equals(INT16_PHASE2))
				wcefPhase2 = wcefField;
			else if (wcefField.getName().trim().equals(INT16_PRIVATE_KEY))
				wcefPrivateKey = wcefField;
			else if (wcefField.getName().trim().equals(INT16_PRIVATE_KEY_PASSWORD))
				wcefPrivateKeyPassword = wcefField;
		}

		Method wcefValue = null;
		if(!noEnterpriseFieldType){
		for(Method m: wcEnterpriseField.getMethods())
			//System.out.println(m.getName());
			if(m.getName().trim().equals("value")){
				wcefValue = m;
				break;
			}
		}
		String tVal;
		eap = noEnterpriseFieldType
				? (String) wcefEap.get(conf)
				: (String) wcefValue.invoke(wcefEap.get(conf), (Object)null);
		tVal = noEnterpriseFieldType
				? (String) wcefPhase2.get(conf)
				: (String) wcefValue.invoke(wcefPhase2.get(conf), (Object)null);
		phase2 = MyWifiTools.removeQuotes(tVal);

		tVal = noEnterpriseFieldType
				? (String) wcefIdentity.get(conf)
				: (String) wcefValue.invoke(wcefIdentity.get(conf), (Object)null);
		identity = MyWifiTools.removeQuotes(tVal);

		tVal = noEnterpriseFieldType
				? (String) wcefAnonymousId.get(conf)
				: (String) wcefValue.invoke(wcefAnonymousId.get(conf), (Object)null);
		anonymous_identity = MyWifiTools.removeQuotes(tVal);

		tVal = noEnterpriseFieldType
				? (String) wcefPassword.get(conf)
				: (String) wcefValue.invoke(wcefPassword.get(conf), (Object)null);
        String val = MyWifiTools.removeQuotes(tVal);
        password = ((val == null || val.equals("*")) ? null : val);

		tVal = noEnterpriseFieldType
				? (String) wcefClientCert.get(conf)
				: (String) wcefValue.invoke(wcefClientCert.get(conf), (Object)null);
		client_cert = MyWifiTools.removeQuotes(tVal);

		tVal = noEnterpriseFieldType
				? (String) wcefPrivateKey.get(conf)
				: (String) wcefValue.invoke(wcefPrivateKey.get(conf), (Object)null);
		private_key = MyWifiTools.removeQuotes(tVal);

		tVal = noEnterpriseFieldType
				? (String) wcefCaCert.get(conf)
				: (String) wcefValue.invoke(wcefCaCert.get(conf), (Object)null);
		ca_cert = MyWifiTools.removeQuotes(tVal);
	}

	public WifiConfiguration get() {
		WifiConfiguration conf = new WifiConfiguration();

		conf.networkId = networkId;
		conf.status = status;
		conf.SSID = MyWifiTools.surroundWithQuotes(SSID);
		conf.BSSID = BSSID;
		conf.preSharedKey = getKey(preSharedKey);
		conf.wepKeys = new String[wepKeys.length];
        for (int j = 0; j < wepKeys.length; j++) {
        	conf.wepKeys[j] = getKey(wepKeys[j]);
        }
        conf.wepTxKeyIndex = wepTxKeyIndex;
        conf.priority = priority;
        conf.hiddenSSID = hiddenSSID;

        conf.allowedKeyManagement = allowedKeyManagement;
        conf.allowedProtocols = allowedProtocols;
        conf.allowedAuthAlgorithms = allowedAuthAlgorithms;
        conf.allowedPairwiseCiphers = allowedPairwiseCiphers;
        conf.allowedGroupCiphers = allowedGroupCiphers;

        try {
			getEnterprisefield(conf);
		} catch (Exception e) {
		}
		return conf;
	}
	private String getKey(String value) {
		if(value == null || value.length() <= 0)
			return null;
		switch(value.length()){
		case 10:
		case 26:
		case 58:
			if(value.matches("[0-9A-Fa-f]*"))
				return value;
			break;
		}
		return MyWifiTools.surroundWithQuotes(value);
	}
	private void getEnterprisefield(WifiConfiguration conf) throws Exception {
		Class[] wcClasses = WifiConfiguration.class.getClasses();
		Class wcEnterpriseField = null;

		for (Class wcClass : wcClasses)
			if (wcClass.getName().equals(INT_ENTERPRISEFIELD_NAME)) {
				wcEnterpriseField = wcClass;
				break;
			}
		boolean noEnterpriseFieldType = false;
		if(wcEnterpriseField == null)
			noEnterpriseFieldType = true;

		Field wcefAnonymousId = null;
		Field wcefCaCert = null;
		Field wcefClientCert = null;
		Field wcefEap = null;
		Field wcefIdentity = null;
		Field wcefPassword = null;
		Field wcefPhase2 = null;
		Field wcefPrivateKey = null;
		@SuppressWarnings("unused")
		Field wcefPrivateKeyPassword = null;

		Field[] wcefFields = WifiConfiguration.class.getFields();
		for (Field wcefField : wcefFields) {
			if (wcefField.getName().equals(INT_ANONYMOUS_IDENTITY))
				wcefAnonymousId = wcefField;
			else if (wcefField.getName().equals(INT_CA_CERT))
				wcefCaCert = wcefField;
			else if (wcefField.getName().equals(INT_CLIENT_CERT))
				wcefClientCert = wcefField;
			else if (wcefField.getName().equals(INT_EAP))
				wcefEap = wcefField;
			else if (wcefField.getName().equals(INT_IDENTITY))
				wcefIdentity = wcefField;
			else if (wcefField.getName().equals(INT_PASSWORD))
				wcefPassword = wcefField;
			else if (wcefField.getName().equals(INT_PHASE2))
				wcefPhase2 = wcefField;
			else if (wcefField.getName().equals(INT_PRIVATE_KEY))
				wcefPrivateKey = wcefField;

			else if (wcefField.getName().trim().equals(INT16_ANONYMOUS_IDENTITY))
				wcefAnonymousId = wcefField;
			else if (wcefField.getName().trim().equals(INT16_CA_CERT))
				wcefCaCert = wcefField;
			else if (wcefField.getName().trim().equals(INT16_CLIENT_CERT))
				wcefClientCert = wcefField;
			else if (wcefField.getName().trim().equals(INT16_EAP))
				wcefEap = wcefField;
			else if (wcefField.getName().trim().equals(INT16_IDENTITY))
				wcefIdentity = wcefField;
			else if (wcefField.getName().trim().equals(INT16_PASSWORD))
				wcefPassword = wcefField;
			else if (wcefField.getName().trim().equals(INT16_PHASE2))
				wcefPhase2 = wcefField;
			else if (wcefField.getName().trim().equals(INT16_PRIVATE_KEY))
				wcefPrivateKey = wcefField;
			else if (wcefField.getName().trim().equals(INT16_PRIVATE_KEY_PASSWORD))
				wcefPrivateKeyPassword = wcefField;
		}

		Method wcefSetValue = null;
		if(!noEnterpriseFieldType){
		for(Method m: wcEnterpriseField.getMethods())
			if(m.getName().trim().equals("setValue"))
				wcefSetValue = m;
		}
		if(eap != null) {
			if(!noEnterpriseFieldType)
				wcefSetValue.invoke(wcefEap.get(conf), eap);
			else
				wcefEap.set(conf, eap);
		}
		if (phase2 != null && !phase2.equals("---")) {
			if(!noEnterpriseFieldType)
				wcefSetValue.invoke(wcefPhase2.get(conf), phase2);
			else
				wcefPhase2.set(conf, MyWifiTools.surroundWithQuotes(phase2));
		}
		if (identity != null && identity.length() > 0) {
			if(!noEnterpriseFieldType)
				wcefSetValue.invoke(wcefIdentity.get(conf), identity);
			else
				wcefIdentity.set(conf, MyWifiTools.surroundWithQuotes(identity));
		}
		if (anonymous_identity != null && anonymous_identity.length() > 0) {
			if(!noEnterpriseFieldType)
				wcefSetValue.invoke(wcefAnonymousId.get(conf), anonymous_identity);
			else
				wcefAnonymousId.set(conf, MyWifiTools.surroundWithQuotes(anonymous_identity));
		}
		if (password != null && password.length() > 0) {
			if(!noEnterpriseFieldType)
				wcefSetValue.invoke(wcefPassword.get(conf), password);
			else
				wcefPassword.set(conf, MyWifiTools.surroundWithQuotes(password));
		}
		if (client_cert != null && client_cert.length() > 0) {
			if(!noEnterpriseFieldType)
				wcefSetValue.invoke(wcefClientCert.get(conf), client_cert);
			else
				wcefClientCert.set(conf, MyWifiTools.surroundWithQuotes(client_cert));
		}
		if (ca_cert != null && ca_cert.length() > 0) {
			if(!noEnterpriseFieldType)
				wcefSetValue.invoke(wcefCaCert.get(conf), ca_cert);
			else
				wcefCaCert.set(conf, MyWifiTools.surroundWithQuotes(ca_cert));
		}
		if (private_key != null && private_key.length() > 0) {
			if(!noEnterpriseFieldType)
				wcefSetValue.invoke(wcefPrivateKey.get(conf), private_key);
			else
				wcefPrivateKey.set(conf, MyWifiTools.surroundWithQuotes(private_key));
		}
	}
}

2011年9月18日日曜日

Version 4.0.0

しばらく更新を行っていませんでしたが、久しぶりにメージャーバージョンアップを行います。(2011年9月末予定)

新たに加えた機能としては、以下2つの機能です。

◆プロバイダへのログイン機能
Wifiへ接続とは別に、各ネットワーク接続提供者へのログインが要求される場合が多いと思いますが、ログイン情報を登録しておきワンタッチないしはWifiに接続後自動的にログインを行う機能です。
現在、docomo、mobilepoint、libedoor-webへのログインが可能なことが確認できています。
ログインに必要なForm情報を解析する機能も提供していますので、ほとんどのプロバイダへのログインが可能だと思います。

◆WifiConfiguratiojnの編集機能
標準のネットワーク接続機能では、Androidで設定可能なWiFi設定ファイルの一部が直接データを入力することができませんが、WifiConfiguratiojnのEnterpriseFieldを含む全ての項目を直接編集する機能をです。ただし、編集時に既に入力してある項目の内、表示可能な情報はAndroidの提供するAPIの範囲となります。したがって、パスワードなどの情報については現在の設定内容を表示することはできません。

なお、本機能を作成するにあたっては
・Wifi Config Editor/OddRain
・WiFi Advanced Config Editor/marcus905
を参考にしています。

このため、Apache Licenseなので、この部分についてはソースを公開したいと思います。