ASP.NET WebPagesと相性のよい w2ui grid

ASP.NET WebPages と Razor(cshtml)の組み合わせに相性のよいTableソリューションを求め歩いていたところ DataTablase に続いて w2ui という優れたライブラリを発見。

w2ui はレイアウト、グリッド、ツールバー、サイドバー、タブ、フォーム、ポップアップその他のユーティリティで構成されるライブラリですが、軽量設計で使いやすくまとまっています。

今回Gridを試したわけですが、このGridの優れたところは、ページングの概念を捨てて「無限スクロール」を導入したこと。しかもその動作は軽快です。

DataTablesと同様にサーバーへは form data、サーバーからはJSONによる応答です。form dataの仕様がこちらのほうが簡単で使いやすいかもしれません。また、開発中の Ver 1.4 には拙翻訳を提供したので日本語表記の利用も可能です。

jQuery DataTablesでやったことと同じことを w2ui を使って再現してみます。

1:  @{  
2:       if (IsPost)  
3:       {  
4:            if (UrlData[0] == "GetList" )  
5:            {  
6:                 var all = System.Globalization.CultureInfo.GetCultures(System.Globalization.CultureTypes.AllCultures).AsEnumerable<System.Globalization.CultureInfo>();  
7:                 var filtered = all;  
8:                 int iDisplayStart = Request["offset"].AsInt(0);  
9:                 int iDisplayLength = Request["limit"].AsInt(10);  
10:                 bool sorted = false;  
11:                 for (int i = 0; Request[String.Format("sort[{0}][field]", i)] != null; i++)  
12:                 {  
13:                      String fld = Request[String.Format("sort[{0}][field]", i)];  
14:                      bool asc = Request[String.Format("sort[{0}][direction]", i)] == "asc";  
15:                      switch( fld)  
16:                      {  
17:                           case "Name":  
18:                                filtered = asc ? filtered.OrderBy(m => m.Name) : filtered.OrderByDescending(m => m.Name);  
19:                                break;  
20:                           case "DisplayName":  
21:                                filtered = asc ? filtered.OrderBy(m => m.DisplayName) : filtered.OrderByDescending(m => m.DisplayName);  
22:                                break;  
23:                           case "TwoLetterISOLanguageName":  
24:                                filtered = asc ? filtered.OrderBy(m => m.TwoLetterISOLanguageName) : filtered.OrderByDescending(m => m.TwoLetterISOLanguageName);  
25:                                break;  
26:                           case "ThreeLetterISOLanguageName":  
27:                                filtered = asc ? filtered.OrderBy(m => m.ThreeLetterISOLanguageName) : filtered.OrderByDescending(m => m.ThreeLetterISOLanguageName);  
28:                                break;  
29:                      }  
30:                      sorted = true;  
31:                 }  
32:                 if (!sorted) { filtered = filtered.OrderBy(m => m.Name); }  
33:                 for (int i = 0; Request[String.Format("search[{0}][field]", i)] != null; i++)  
34:                 {  
35:                      String fld = Request[String.Format("search[{0}][field]", i)];  
36:                      String sSearch = Request[String.Format("search[{0}][value]", i)];  
37:                      if (!String.IsNullOrEmpty(sSearch))  
38:                      {  
39:                           switch (fld)  
40:                           {  
41:                                case "Name":  
42:                                     filtered = filtered.Where(m => m.Name.Contains(sSearch));  
43:                                     break;  
44:                                case "DisplayName":  
45:                                     filtered = filtered.Where(m => m.DisplayName.Contains(sSearch));  
46:                                     break;  
47:                                case "TwoLetterISOLanguageName":  
48:                                     filtered = filtered.Where(m => m.TwoLetterISOLanguageName.Contains(sSearch));  
49:                                     break;  
50:                                case "ThreeLetterISOLanguageName":  
51:                                     filtered = filtered.Where(m => m.ThreeLetterISOLanguageName.Contains(sSearch));  
52:                                     break;  
53:                           }  
54:                      }  
55:                 }  
56:                 var output = new  
57:                 {  
58:                      status = "success",  
59:                      total = filtered.Count(),  
60:                      records = filtered.Skip(iDisplayStart).Take(iDisplayLength).AsEnumerable().Select((o, i) => new { recid = o.Name, o.Name, o.DisplayName, o.TwoLetterISOLanguageName, o.ThreeLetterISOLanguageName })  
61:                 };  
62:                 Response.ContentType = "application/json";  
63:                 Response.Write(Json.Encode(output));  
64:                 Response.End();  
65:                 return;  
66:            }  
67:       }  
68:  }  
69:  <script src="http://ajax.aspnetcdn.com/ajax/jquery/jquery-1.9.0.js"></script>  
70:  <link rel="stylesheet" href="http://w2ui.com/src/w2ui-1.3.min.css" type="text/css" />  
71:  <script src="http://w2ui.com/src/w2ui-1.3.min.js"></script>  
72:  <script>  
73:    $(document).ready(function () {  
74:         $('#sampleTable').w2grid({  
75:              name: 'grid',  
76:              header: 'List of Names',  
77:              show: {  
78:                   toolbar: true,  
79:                   footer: true  
80:              },  
81:              columns: [  
82:                      { field: 'Name', caption: 'Name', size: '20%', sortable: true, attr: 'align=center' },  
83:                      { field: 'DisplayName', caption: 'DisplayName', size: '30%', sortable: true, resizable: true },  
84:                      { field: 'TwoLetterISOLanguageName', caption: 'TwoLetterISOLanguageName', size: '30%', sortable: true, resizable: true },  
85:                      { field: 'ThreeLetterISOLanguageName', caption: 'ThreeLetterISOLanguageName', size: '30%', resizable: true }  
86:              ],  
87:              searches: [  
88:                      { field: 'Name', caption: 'Name', type: 'text' },  
89:                      { field: 'DisplayName', caption: 'DisplayName', type: 'text' },  
90:                      { field: 'TwoLetterISOLanguageName', caption: 'TwoLetterISOLanguageName', type: 'text' },  
91:              ],  
92:              sortData: [{ field: 'Name', direction: 'ASC' }],  
93:                 url: '@Href(Request.AppRelativeCurrentExecutionFilePath,"GetList")'  
94:         });  
95:    });  
96:  </script>  
97:  <div>  
98:       <div id="sampleTable" style="height: 600px;">  
99:       </div>  
100:  </div>  

ASP.NET WebPagesと相性のよい jQuery DataTables

ASP.NET WebPages (MVCではない)で、Razor(cshtml)で書くのがマイブームです。ASPXより圧倒的に書きやすく、MVCほどコードの分散が起こらず、一人でコードを書くには最適な選択だと感じています。

さて、cshtml上で、サーバーサイドのデータでもって、ページング、ソート、フィルター付きのテーブルを探していた時に jQuery DataTables にたどり着きました。ほかにも類似のTableソリューションはたくさんありますが、これが、軽量、簡単で ASP.NET Web Pagesと非常に相性がいいと思ったので紹介します。

「DataTables https://datatables.net/index はjQueryのプラグインライブラリで、HTMLのtableに機能を追加する形で動作します。」

詳細は原典を参照してもらうことにし、ASP.NET Web Pages から使用する場合のキーポイントに絞ると

  • AJAXによるサーバーサイドからのデータの取り出しに対応。
  • サーバーサイドのページング、ソート、フィルター(検索)に対応している。
  • サーバーへのリクエストは FORMエンコーディングで、サーバー側のパラメータの取り出しに Request.Form が使える。
  • クライアントへの応答は json で、サーバーからは Json(System.Web.Helpers.Json)で簡単に応答できる。
  • 受け渡すデータは型が規定されていない(ただの配列渡し)のでルーズだが、簡単。サーバーサイドでLINQと anonymous object を組み合わせれば非常に簡単。

サンプルとしてシステムにある System.Globalization.CultureInfo を列挙してテーブルに表示するコードを書いてみました。1ページアプリとしてもこんなに簡単に短く、高機能テーブルを書くことができました。

http://www.yo-ki.com/study/ASPNET/ExperimentDataTables

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
@{
    if( IsPost ){
        if( UrlData[0] == "GetList" ){
            String sEcho = Request.Form["sEcho"];
            int iDisplayStart = Request.Form["iDisplayStart"].AsInt(),
                iDisplayLength = Request.Form["iDisplayLength"].AsInt(),
                iSortingCols = Request.Form["iSortingCols"].AsInt();
            String sSearch = Request.Form["sSearch"];
            var data = new List<object>();
            var all = System.Globalization.CultureInfo.GetCultures(System.Globalization.CultureTypes.AllCultures);
            var filtered = all.AsEnumerable<System.Globalization.CultureInfo>();
            if( !String.IsNullOrEmpty(sSearch) ){
                filtered = filtered.Where(p => p.DisplayName.Contains(sSearch) || p.Name.Contains(sSearch) || p.ThreeLetterISOLanguageName.Contains(sSearch) || p.TwoLetterISOLanguageName.Contains(sSearch));
            }
            for( var i=0; i<iSortingCols; i++ ){
                var iSort = Request.Form["iSortCol_" + i].AsInt(-1);
                var ascending = Request.Form["sSortDir_" + i];
                if( ascending == "asc" ){
                    filtered = filtered.OrderBy(p => iSort == 0 ? p.Name : iSort == 1 ? p.DisplayName : iSort == 2 ? p.TwoLetterISOLanguageName : p.ThreeLetterISOLanguageName);
                }
                else
                {
                    filtered = filtered.OrderByDescending(p => iSort == 0 ? p.Name : iSort == 1 ? p.DisplayName : iSort == 2 ? p.TwoLetterISOLanguageName : p.ThreeLetterISOLanguageName);
                }
            }
            var result = filtered;
            foreach( var ci in filtered.Skip(iDisplayStart).Take(iDisplayLength) ){
                var row = new List<object>();
                row.Add(ci.Name);
                row.Add(ci.DisplayName);
                row.Add(ci.TwoLetterISOLanguageName);
                row.Add(ci.ThreeLetterISOLanguageName);
                data.Add(row);
            }
            Response.Clear();
            Response.ContentType = "text/json";
            Response.Write( Json.Encode(new {
                sEcho = sEcho,
                iTotalRecords = all.Count(),
                iTotalDisplayRecords = filtered.Count(),
                aaData = data
            }));
            Response.End();
            return;
        }
    }
}
<script src="http://ajax.aspnetcdn.com/ajax/jquery/jquery-1.9.0.js"></script>

<link rel="stylesheet" href="http://ajax.aspnetcdn.com/ajax/jquery.dataTables/1.9.4/css/jquery.dataTables.css" type="text/css"/>
<script src="http://ajax.aspnetcdn.com/ajax/jquery.dataTables/1.9.4/jquery.dataTables.js"></script>

<script>
    $(document).ready(function () {
        $("#sampleTable").dataTable({
            "bProcessing": true,
            "bServerSide": true,
            "bPaginate": true,
            "sPaginationType": "full_numbers",
            "sServerMethod": "POST",
            "sAjaxSource": '@(Request.Path)/GetList'
        });
    });
</script>
<div>
    <table id="sampleTable">
        <thead>
            <tr><th>Name</th><th>DisplayName</th><th>TwoLetterISOLanguageName</th><th>ThreeLetterISOLanguageName</th></tr>
        </thead>
        <tbody>
        </tbody>
    </table>
</div>

VAIO DUO 11をWiMAX - WiFi アクセスポイントにする方法(マニュアル設定編)

ここでは WiMAX 搭載 SONY VAIO DUO 11 を前提に、WiFiアクセスポイントとして動作させるための方法を紹介します。

特別に必要なもの

  • USB WiFi アダプター

私は Logitechの LAN-W300N/U2S というUSBアダプターを使いました。一般的に動作可能であればなんでもいいでしょう。

前置き

VAIO DUO 11ではオーダーメイドで構成としてWiMAX搭載を選択することができます。VAIO単体で電源オンからすぐにネットへつながる便利さは格別です。DUO11を中心にネット環境を充実させるべく次に考えることが、DUO11をWiMAX母艦にして、周辺のデバイス(スマートフォンやタブレットなど)からWiFi経由でインターネットを利用したいということです。

ところが、DUO11には、これを実現するために致命的な問題が1つあります。「WiMAXを使用中はWiFiデバイスは使用できない」というもの。つまりWiMAXとWiFiは排他利用だということです。これは、Intel のワイヤレスデバイスの仕様によるもので、OSやソフトなどではどうしようもないのです。

そこで、次善のアイデアとして別途USBでWiFiアダプタを追加してやればそれを通じてWiMAXを共有できるかもしれないというものです。

手順

ここで紹介する手順はコマンドプロンプトを管理者モードで操作するもので、自信のある方のみ自己責任でチャレンジしてください。

1.USB接続のWiFiアダプタが正常にインストールされているか確認

2.本体に内蔵のWiFiアダプタを「無効」に

 

3.コマンドプロンプトを管理者モードで開きます。

C:\Windows\system32>netsh wlan set hostednetwork mode=allow ssid="DUO11WiMAX" key="ILoveDuo11"

ssidはその名の通りアクセスポイントの公開名称となるSSID。keyは接続するときのパスワードになります。正常に実行されれば次のように表示されます。

ホストされたネットワーク モードは許可に設定されています。
ホストされたネットワークの SSID が正常に変更されました。
ホストされたネットワークのユーザー キー パスフレーズが正常に変更されました。

次のコマンドでWiFiアクセスポイントをスタートさせます。

C:\Windows\system32>netsh wlan start hostednetwork

ホストされたネットワークが開始しました。

この時点で、「ネットワーク接続」にSSIDの名前とともに新しい接続(ここでは「ローカルエリア接続16 Microsoft Hosted Network Virtual Adapter 」という名前)が1つ増えていることを確認します。

4.WiMAXの��ダプタを「インターネット共有」モードに設定します。

「ローカルエリア接続 Intel Centrino  WiMAX 6150」を右クリックしてプロパティを開き、共有のタブをクリックします。

「ネットワークの他の・・・許可する」をチェックして、ホームネットワーク接続から先ほど確認した Microsoft Hosted Network Virtual Adapter である「ローカルエリア16」を選択します。

OKを押してプロパティを閉じるとようやくWiFi経由でWiMAXが使えるようになります。

 

 

5.元に戻す場合

使い終わって、元に戻す場合は次の3点

  1. コマンドプロンプトから
    C:\Windows\system32>netsh wlan stop hostednetwork
  2. 共有プロパティからチェックをはずしてOKを押す。
  3. 「無効」設定したWiFiアダプタを再び「有効」に戻す。

 

 

 

 

 

Yokin's 2ch Browser を Windows ストアアプリで公開

2015年3月から2ch専用ブラウザに関して2ch運営元の方針変更により当アプリはWindowsストアから撤去する予定です。ご利用ありがとうございました。

Windows 8/RT のいわゆるストアアプリ (Windows Store App)のプログラミングから登録手続きまでの流れの学習を兼ねて作成しました。2chリーダーです。アプリストアで検索したところでは、いまだ2chリーダーは登録されていないようでしたので、気合を入れて作ってみました。Androidでは 2chMate にいつもお世話になっているので、仕様は2chMateを強く意識した作りにしました。

http://apps.microsoft.com/windows/ja-JP/app/yokins-2ch-browser/203ac772-a869-4c3d-ac09-0e5d9b4499a1

主な実装済みの機能は

  • 板一覧 -> スレッド一覧 -> 記

    事 までの UIをWindowsアプリの作法でナビゲーション

  • 各板のバナー画像を自動的に取得
  • URLからブラウザを起動
  • 書き込み内の画像リンクとYoutubeリンクのサムネイルを表示

近く実装したい機能は

  • スレッドのソート
  • 記事のソート機能(タグによる参照順など)
  • IDによるフィルター
  • 各種設定画面の追加

いずれ必要な機能は

  • Sync2ch 対応
  • 書き込みの機能

各所でお世話になっていることもあり、アプリ自体はフリーですが、Microsoft Advertising の広告を使用しています。Microsoftアプリストアを通じてダウンロード数や、ユーザーの反響などが得られるようなので、そちらを通じても、応援いただけたら機能追加の励みになります。

 

 

SONY VAIO DUO11の個人的評価

購入から1か月ほど経過したため簡単に個人的な評価を書いてみようと思います。

プロセッサ・メモリ

ネットの閲覧、動画・音楽の再生など通常の使用には問題なし。

ストレージ

オフィスを追加的に入れても空き容量は50GB。巨大な動画ファイルや大量の画像を保存するわけでもないので問題なし。

WiMAX

docomo LTEのXperia GXでテザリングして使う予定で、その保険としてWiMAXもつけました。携帯でのテザリングの不安定さに辟易した結果WiMAXを契約。オプションとしてつけておいて正解。LTEと比べると今や速度的にはそれほどアドバンテージがあるとはいなくなりましたが、接続の安定性は抜群。安心して使えます。ただIntelのWiMAXチップセットはWiFiと排他利用となるため、DUO11自身をWiMAX回線のアクセスポイントとして使うことができません。小型のUSB WiFiアダプターを追加すればできるかもしれませんが、未確認です。

USB WiFiアダプタを使ってWiMAXのアクセスポイントにする実験成功しました。

GPS×

Androidタブレットのノリでつけてみましたが、どうもGPSを使えるWindowsのアプリ(標準の地図プリを含む)がほとんどなく、宝の持ち腐れとなりました。

HDウェブカメラ×

これも、Androidタブレット的に、簡単にTwitterなどへ投稿するための写真が撮れたらと思って背面のカメラをつけてみましたが、本体が想像以上に重く、気軽に持ち上げて写真を撮る気も起らず、また、画質も最近の携帯についているものと比べるとありえないほど悪くがっかりでした。

キーボード○

個人的な趣味になりますが、英字キーボードを選択しました。おかげで、海外通販でキーボードカバーを入手して使うことができました。ご興味の方はAliexpressからどうぞ。

http://ja.aliexpress.com/wholesale?SearchText=SONY+VAIO+DUO11&catId=0

 

 

キーボードバックライト

こちらも、趣味の範囲と思い、省略。

拡張シートバッテリー○

かつてSONYストアで5000円で追加できた時期もあったようですが、私の時はそうではなく、また、巷で購入してもほとんど定価売り。ヨドバシカメラなら10%がポイントで戻ってくるので、結局あとで勝ったほうがお得ということで先延ばしにしました。DUO11を使い始めてからはやはりバッテリの持続時間は3時間前後といったところで、1日外にいるときなど、電源なしではとてもやってられません。そこで、シートバッテリですが、つけてさらに重く、背面のカメラで撮影とは、片手で支えるには重すぎの状態になりますが、それでも、フル充電で7時間前後の残り時間が表示されひとまず安心といったところです。日中の外出はあえてアダプターを置いて出ても大丈夫そうです。

 

 

Androidの非同期通知機能 Google Cloud Messaging (GCM) のサーバー側コードをC#で書いてみた

.NETの標準以外に Newtonsoft のJSON.NETを使用します。http://james.newtonking.com/pages/json-net.aspx
使い方は

    var container = new Google.GoogleCloudMessaging.Container {
        RegistrationIds = new String [] { "APA*******PQZQ" },
        Data = new { message = "Hello World!" }
    };
    var response = Google.GoogleCloudMessaging.Broadcast( "AIz************", container );

のようになります。

------------------------------

 

using System;
using System.Net;

using Newtonsoft.Json;

namespace Google
{
    public class GoogleCloudMessaging
    {
        public class Container
        {
            [JsonProperty("registration_ids")]
            public String[] RegistrationIds { get; set; }
            [JsonProperty("collapse_key", NullValueHandling=NullValueHandling.Ignore )]
            public String CollapseKey { get; set; }
            [JsonProperty("data", NullValueHandling = NullValueHandling.Ignore)]
            public object Data { get; set; }
            [JsonProperty("delay_while_idle", NullValueHandling = NullValueHandling.Ignore)]
            public Boolean? DelayWhileIdle { get; set; }
            [JsonProperty("time_to_live", NullValueHandling = NullValueHandling.Ignore)]
            public int? TimeToLive { get; set; }
            [JsonProperty("restricted_package_name", NullValueHandling = NullValueHandling.Ignore)]
            public String RestrictedPackageName { get; set; }
            [JsonProperty("dry_run", NullValueHandling = NullValueHandling.Ignore)]
            public Boolean? DryRun { get; set; }
        }
        public class Response
        {
            [JsonProperty("multicast_id")]
            public String MulticastId { get; set; }
            [JsonProperty("success")]
            public int Success { get; set; }
            [JsonProperty("failure")]
            public int Failure { get; set; }
            [JsonProperty("canonical_ids")]
            public int CanonicalIds { get; set; }
            [JsonProperty("results")]
            public Result[] Results { get; set; }
        }
        public class Result
        {
            [JsonProperty("message_id")]
            public String MessageId { get; set; }
            [JsonProperty("registration_id")]
            public String RegistrationId { get; set; }
            [JsonProperty("error")]
            public String Error { get; set; }
        }
        static public Response Broadcast(String API_KEY, Container container)
        {
            var request = WebRequest.Create("https://android.googleapis.com/gcm/send");
            var json = Newtonsoft.Json.JsonConvert.SerializeObject(container);
            using( WebClient web = new WebClient()){
                web.Headers.Add("Authorization", "key=" + API_KEY );
                web.Headers.Add("Content-Type", "application/json");
                byte[] result = web.UploadData("https://android.googleapis.com/gcm/send", "POST", System.Text.Encoding.UTF8.GetBytes(json) );
                String resultString = System.Text.Encoding.UTF8.GetString(result);
                var response = Newtonsoft.Json.JsonConvert.DeserializeObject<Response>( resultString );
                return response;
            }
        }
    }
}

Windows Server 2008 R2 Hyper-V 2.0 上に CentOS 6.2をインストールする際のメモ

想定環境は:

一部始終はこちらの方のブログにわかりやすく解説されています。

http://sashiz.seesaa.net/article/253087250.html

 

ただし、これに加えて陥った問題ありました。ヘビーなファイル転送などで高負荷になった時にディスクドライバがエラーをはきアクセス不能になったり、カーネルパニックを起こしてしまったりが頻発しました。いろいろ対処法を探し回りましたが結局、やってみて効果が認められたのは kernel のオプション設定です。

情報はVMWareのKnowledge Baseで解説されています。

http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1006427

/boot/grub/brub.conf ファイルの kernel 行に1こと追加します。

今回の環境では clocksource=acpi_pm divider=10 (64bit 32bit 共)

kernel /vmlinuz-2.6.32-220.13.1.el6.x86_64 ro root=/dev/mapper/VolGroup-lv_root rd_NO_LUKS LANG=en_US.UTF-8 rd_NO_MD rd_LVM_LV=VolGroup/lv_swap SYSFONT=latarcyrheb-sun16 rhgb crashkernel=auto quiet  d_LVM_LV=VolGroup/lv_root  KEYBOARDTYPE=pc KEYTABLE=us rd_NO_DM  clocksource=acpi_pm divider=10

 注意)試行錯誤が続いていますが 私の利用している CentOS 6.2 x86_64 のカーネルは notsc をサポートしていない様子で、notscオプションを付けると別のデフォルトクロックを使用して動作するようでした。その結果再び悪夢のカーネルパニックに陥ってしまいました。したがって notsc オプションは意図的に除外することにしました。

 

注意更新)それでも高負荷時に kernel panic に陥るため再調整を行いました。clocksource オプションを指定しないとデフォルトで hyper-v の指定する hv_timesource が選択されていたところ、明示的に acpi_pm を指定しました。結果、SAMBAのファイル転送が敵的に早くなったのを確認。安定性についてはしばらく様子を見ます。

さらに、システムクロックが少しずつ早くなるという問題があります。少しずつなのですが、Linux上にSAMBAを立ち上げてADS認証などを設定しているとドメインコントローラと自国のずれが大きくなるとKerberos認証にエラーが変えるようになってしまい致命的です。

CentOS6のデフォルトでは ntp はインストールされてないようなので追加の必要あり。

yum install ntp

chkconfig ntpd on

service ntpd start

 

 原因と対策はまとめると次の通り

  • 最近のLinux Kernel ではシステムの割り込みタイマーが早すぎる
    → カーネルに  divider=10 オプション 
  • clocksource にhyper-vの hv_timesource が選択されていると不安定
    → カーネルに clocksource=acpi_pm オプション 
  • Hyper-V ホストとの時刻同期はGuest OSが5秒以上遅れた時だけ発動する
    →期待しすぎて陥るトラップですが、GuestOSの時計が進みすぎると誰も補正してくれないという仕様
    つまり正確を期すにはLinux OS上にNTPDを設定して、定期的に自分で時刻を合わせなさい。 

 

いまのところ落ちたりせずに動作しています。意外に、Hyper-VとLinuxの組み合わせの情報が多くないので、参考までに。

 

SoftbankでSIMフリーHTC Desireと最近のAndroid HTC Sense系 ROM(含備忘録)

海外で購入したHTC DesireにいろんなROMを焼いてしばらくこの話題から遠ざかっていました。気がつくとSoftbankからたくさんのAndroid端末が発売されており、その間に andglobal.softbank.ne.jp なる新しいAPNも設定されていました。

Softbankでの契約内容と使用可能なAPNの組み合わせについて 2ch でまとめられていたものを備忘録としてここにコピーしておきます。

 

◆パケットし放題S(3G) 

mailwebservice.softbank.ne.jp → ウェブ 

のみの接続であれば上限4,410円で定額 

open.softbank.ne.jp → PCダイレクト 

smile.world → PCダイレクト 

は上限が9,800円。 

andglobal.softbank.ne.jp → スマートフォン通信 

は青天井(未確認) 

 

◆パケットし放題フラット(iPhone、3G) 

ウェブ PCダイレクト分のみ定額になる。黒simフラット契約、銀simガラケー共に 

open.softbank.ne.jp → PCダイレクト 

smile.world → PCダイレクト 

mailwebservice.softbank.ne.jp → ウェブは定額範囲だったが、 

andglobal.softbank.ne.jp → スマートフォン通信 

に設定すると定額外で別枠だった。パケ死する恐れあり。 

Desireだとフラット契約を適用できたが、DHDでパケットし放題フラットを適用できなかったのも、 

APNとプランの設定で範囲で、初期DHD内でのAPNがandglobalな為、定額外扱いだからだと思われる。 

 

◆パケットし放題S forスマートフォン 

◆パケットし放題MAX forスマートフォン(受付終了) 

現時点(2011/5/10)では、銀Simでも緑Simでも 

mailwebservice.softbank.ne.jp → ウェブ(ガラケー扱い) 

open.softbank.ne.jp → PCダイレクト 

andglobal.softbank.ne.jp → スマートフォン通信 

smile.world → PCダイレクト 

のどれも定額内。 

(緑sim用の機種ならandglobal、銀sim用の機種Xシリーズならopenに接続されるが、契約はどちらでも同じ。) 

 

◆パケットし放題フラット forスマートフォン(2011/05/01より) 

・SoftBankスマートフォン(Xシリーズの場合、最新の販売履歴がXシリーズであること)のみ、お申し込みいただけます。 

・国内でご利用のS!メール[MMS]送信・読出料、ウェブ・PCサイトブラウザ(PCメールを含む)・PCサイトダイレクト(Xシリーズ専用)通信料が定額の対象となります。 

スマホ用プランでパケットし放題MAX/Sと同様となので 

mailwebservice.softbank.ne.jp → ウェブ(ガラケー扱い) 

open.softbank.ne.jp → PCダイレクト 

andglobal.softbank.ne.jp → スマートフォン通信 

smile.world → PCダイレクト 

のどれも定額内と思われる。 

 

あと、私自身がひっかかった非常に重要な落とし穴として最近のHTC DesireのROMにははじめからSoftbankのAPN設定が含まれていますが、中に andglobal な設定しかないROMがあり、こういったROMを焼いてAndroidが起動、アカウントでサインインすると、以前のバックアップとアプリのダウンロードをすべくネットに自動的に接続に行きます。この間有無を言わさず通信が始まりますからどこのAPNに接続しているか未確認の状態では非常に危険です。

/system/etc/apns-conf.xmlの内容を十分確認するか、SIMを抜いた状態で初期設定を行うなど気を使う必要があります。

皆様もご注意ください。

台湾でプリペイドSIM - 遠傳電信 FarEasTone編

今回台湾で4日ほど滞在する際に、我がHTC Desire(UK版SIMフリー)でパケット通信すべくプリペイドSIMを購入しました。

手続きについてはこちらのサイトを参考にさせて頂きました。

http://blog.nabe.jp/archives/000211.html

台北駅新光三越裏の店舗カウンターでプリペイドSIMを購入したいと伝えると、1日100NTD 3日間250NTD 5日間350NTDのプランがあるとのこと。手続きにはパスポートのほかにもう一つ日本での身分証明書が要求されましたので私の場合は運転免許証を使いました。

登録手続きから開通まで1時間かかるという説明を受けましたが実際には手続きをしていろいろ説明を聞いているうちに開通したようですぐに利用可能でした。

作業の手順としてはSIMを携帯に刺して、ネットワークの選択でFarEasToneを選択、その後アクセスポイントの設定でAPNを internet になっていたものを f3prepaid に変更。あとは携帯を再起動すると完了です。携帯上でアクティベーションなどの作業はありませんでした。

購入したNT$350は5日間の無制限3Gデータ通信用で、音声通話用のクレジットは含まれていませんでした。ただし電話番号はありますからSMSの受信、音声通話の着信は可能です。

ちなみに、私は中国語はカタコトですが、店頭では英語が通じるスタッフが一人いたためお陰でほぼ英語だけで滞り無くコミュニケーション可能でした。

ASUS Eee Pad Transformer 日本版JP SKUで NVFLASH PRIME1.6 Honeycomb 3.1に

日本版 JP SKUに海外版 US WW TW CNなどのASUS公式ROMで上書きしてアップデートをかけることはできません。私自身は言語バージョンはどれでもよくROOT化やその他の「やばい」方法を使わなくても首尾よくAndroid 3.1に上げられればいいと思っていましたが、やはりこらえきれずやってしまいました。

世の中には Gingerbreakというものを使ってROOTを奪取し、その後ROMを入れていくという方法もあるようですが、こちらはちょっと「怖そう」なので遠慮して、見るからに簡単そうに見えたNVFLASHによる方法でチャレンジしました。

手順はこのサイトのもの。

http://tabletroms.com/forums/showthread.php?976-Nvflash-Unbricking-and-forever-root!

詳細は省略しますが、NVFLASHのパッケージとPRIME1.4のイメージファイル(****.imgファイル3つを含んだ物)の2種類を取ってきます。あと img ファイルはNVFLASHと同じディレクトリにちゃんとコピーしておくこと。これをわすれて download.batを実行してTransformerがまっさらになったところで処理が止まって大変なことにんなりかねません。

待つこと数分・・・・

自動的に再起動してなにやら処理が進んで・・・・Androidの初期設定画面にたどり���きます。その後はまっさらのAndroidにWifiのパスワードなどを設定、Googleのアカウントを設定すればしばらくしてアプリなど以前使っていたバックアップが自然と降りてきます。

PRIME 1.4のROMですがこの時点で

  • Androidバージョンは 3.1 
  • ROOT化されています。(adb shell で # が表示されます。)
  • ClockworkMod Recovery v3.1.0.1が導入済み(各所で配布されているROMが導入できます)
  • キーボード配列は英語キーボード
  • FSKARENはもちろん含まれていません。

さて、これからが作業ですが、まず現時点で最新のPRIME 1.6のROMを導入します。

http://forum.xda-developers.com/showthread.php?t=1052380

Transformerを「リカバリ」で再起動して、リカバリのメニューを駆使してMicroSDに保存しておいたZIPファイルを選択してアップデート。ボリュームの上下でメニューの移動、電源ボタンが「選択」操作になっています。

次にNVFLASHする前に、日本阪の状態の時にADBを通じてコピーしておいたファイルをPUSHします。この作業前に忘れずに system を mountしておきます。2カ所に同じファイルを転送するのは1つはAndroidキーボード用でもう一つはxt9つまりASUSキーボード用です。

  • adb push asusec-ja_JP.kcm /system/usr/keychars/asusec.kcm
  • adb push asusec-ja_JP.kl /system/usr/keylayout/asusec.kl
  • adb push asusec-ja_JP.kl /system/usr/xt9/keylayout/qwerty-ja_JP.kl
  • adb push asusec-ja_JP.kcm /system/usr/xt9/keychars/qwerty-ja_JP.kcm

リカバリモードはこれで終了。

※JP SKUに含まれていたキーマップ関連のファイルをZIPにしました。(おそらく再配布にに関して問題はないと・・・)あくまで参考までにご利用くださいませ。keymapfiles_in_3.0_JP_SKU.zip (6.22 kb)

rebootしてから最後に FSKAREN.apk をインストール

  • adb install .........\FSKAREN.spk

 

さてここまできましたがやはりうまくいかなかったものが・・・日本語について

  • FSKARENはインストールできますが、設定画面で落ちます。入力方法として選択してもやはり落ちます。つまり動作しません。
  • ASUS Keyboardで日本語のキーボードレイアウトを選択することができません。どこかに言語リストがあるのかも・・・

現在の最終型はこのとおりです。