2012/03/23

ソフトバンクで店頭に行かずに機種変更した





DELL Streak Pro 101DLをソフトバンクオンラインで購入して、Web上で機種変更手続きをやってみた。

全部オンラインで完結するので、非常に便利でした。






参考までに、購入~手続きの大まかな流れをまとめておきます。
店頭に行くと、訳の解らん契約を勧められたりする場合もあるので、
これからもオンラインでやってこうと思います。



  1. ソフトバンクオンラインで端末購入
    いろんな規約の確認がありますが、店頭で要領の得ない話を聞くより断然マシです。
    フツーのオンラインショップのように購入手続きできました。
  2. すぐに「発送準備完了のお知らせ」とかいうメールが来ます。
    そこに機種変更手続きに関する説明も記載されています。
  3. 2日くらいすると、「出荷完了のお知らせ」というメールが来ます。
    このメールの後半に、端末切り替えに必要な「お申し込み受付番号」が記載されているので破棄しないように注意。
  4. 端末が届いたら、同梱されているUSIMカードを新しい端末に挿します。
    (カードを挿すとき、端末の電源はOFFにしとけとマニュアルにありました。)
  5. 「出荷完了のお知らせ」メールにWebで端末切り替えるURLが記載されているので、おもむろにクリックします。
    先ほどの受付番号と生年月日、メールアドレスを入力します。

    処理の完了に30分くらいかかるようです。
    先に端末の電源をONにし、Wi-Fi環境でGoogleアカウントのセットアップをしておきます。
  6. しばらくすると「手続き完了のお知らせ」が届きます。

    が、一向に新しい端末のアンテナが立たない。
    どうやら切り替えの反映には、端末の再起動が必要な模様です。
    (30分くらい悩んでしまった・・・)

    端末を再起動すると無事3G通信出来るようになり、電話番号も認識してました。
    旧端末も再起動すると、3G通信が無効になりました。

    起動しっぱなしだと、アンテナは立っているように見えましたが、おそらく使用できない状態なんでしょう。
    確認してませんが。

作業自体は非常に簡単でした。
店頭に行くと待ち時間の方が長いなんてこともザラなので、
オンラインで全て完結するのは嬉しいです。


2012/03/05

[Android] 連絡先の取得


getContentResolver()を使用する。


android.database.Cursor c = getContentResolver().query(
 Data.CONTENT_URI,
 new String[]{...}, //取得するColumnを指定。 nullだと全Column
 ".....", //where句に該当、条件を指定しない場合はnull
 new String[]{...}, //プレースホルダに設定する値。上記where句の?に順にセットされる
 "....." //ORDER BY句。nullだと順序を指定しない。
);


getContentResolverメソッドはandroid.content.ContextWrapperクラスに定義されていて、 android.app.ActivityはContextWrapperを継承している。


取得例 [http://developer.android.com/intl/ja/reference/android/provider/ContactsContract.Data.html]
Cursor c = getContentResolver().query(Data.CONTENT_URI,
 new String[] {Data._ID, Phone.NUMBER, Phone.TYPE, Phone.LABEL},
 Data.CONTACT_ID + "=?" + " AND "
  + Data.MIMETYPE + "='" + Phone.CONTENT_ITEM_TYPE + "'",
 new String[] {String.valueOf(contactId)},
 null);



アプリケーションでContactへの参照を保持する場合は、android.provider.ContactsConstract.Contacts.LOOKUP_KEYを使用する。

//String lookupKey <- 保持しているLOOKUP_KEY
//lookupKeyからURIを組み上げる
android.net.Uri lookupUri = Uri.withAppendedPath(Contents.CONTENT_LOOKUP_URI, lookupKey);

//URIからContactを取得
android.database.Cursor c = getContentResolver().query(
 lookupUri, new String[]{ Contacts.DISPLAY_NAME }, ....
);

try{
 c.moveToFirst();
 String displayName = c.getString(0);
}finally{
 c.close();
}



パフォーマンスに配慮するなら、LOOKUP_KEYのほかにCONTACT_IDを保持し、 android.provider.ContactsConstract.Contacts.getLookupUri()を使用して URIを取得する。


getLookupUri()では、最初に CONTACT_IDを使用してContactを探し、ヒットしなければLOOKUP_KEYを使用する。


Uri lookupUri = getLookupUri(contactId, lookupKey);


Contactの集約により、CONTACT_IDは変化する可能性があるため、データの参照には常にURIを使用する必要がある。




2012/02/20

JavaScript (WSH) でExcelファイル読み込み

Excelのテーブル定義書を元に、Java Beansの元となるテキストを作成するJavaScriptを書きました。
14行目からのCELL objectの定義を少し修正すれば、汎用的に使えると思います。

行が結合されてたりすると、途端に破綻してしまいますが...。

/*
 * Excelファイル読み込み
 * テーブル定義書から必要な情報を取得し、classの元データを生成する
 */

/** Excelファイル */
var XLS_FILES = [
 "3.1. テーブル定義\\テーブル定義書_1.xls",
    :
 "3.1. テーブル定義\\テーブル定義書_N.xls"
];

/** Cell位置定義 */
var CELL = {};
/** テーブル名 (物理名) */
CELL.TABLE_NAME_ROW = 8;
CELL.TABLE_NAME_COL = 1;
/** テーブル名 (正式名) */
CELL.TABLE_DESC_ROW = 8;
CELL.TABLE_DESC_COL = 12;

/** フィールド情報 開始位置定義 */
CELL.START_ROW = 10;
CELL.FIELD_NAME_COL = 4;  //フィールド名
CELL.FIELD_TYPE_COL = 12; //種類
CELL.FIELD_DESC_COL = 18; //概要

/** テーブル定義 シート名 */
var SHEET_NAME = 'フィールド';

var fso = new ActiveXObject('Scripting.FileSystemObject');


/**
 * Excelファイルを開く
 */
function readExcel(xlsFile){
 //ファイル存在チェック
 if( ! fso.FileExists(xlsFile) ){
  return;
 }
 
 var xls = null;
 var book = null;
 var fields = [];
 
 try{
  //Excel起動
  xls = new ActiveXObject('Excel.Application');
  //Excelファイル open
  book = xls.Workbooks.Open(xlsFile);
  //シート指定
  var sheet = book.WorkSheets(SHEET_NAME);

  // sheet.Cells(row, col);
  var tableName = sheet.Cells(CELL.TABLE_NAME_ROW, CELL.TABLE_NAME_COL).Value;
  var tableDesc = sheet.Cells(CELL.TABLE_DESC_ROW, CELL.TABLE_DESC_COL).Value;
  /*
   table = {
   name:
   description: 
   }
   */
  fields = [{ 'name':tableName, 'description':tableDesc }]; //1要素目はtable名
  /*
  field = {
   name:
   type:
   length:
   description:
  }
  */

  var reg = /\([0-9]+\)/;
  var row = CELL.START_ROW;
  while(1){
   var c = sheet.Cells(row, CELL.FIELD_NAME_COL).Value;
   if( c == null || c.length == 0){
    //フィールド名定義がない→ループ終了
    break;
   }
   //フィールド名
   var name = c;
   //種別
   var type = sheet.Cells(row, CELL.FIELD_TYPE_COL).Value;
   //長さ
   var length = 0;
   if( reg.test(type) ){
    var m = type.match(reg).join('');
    m = m.replace(/\(|\)/, '');
    length = parseInt(m);
   }
   //概要
   var desc = sheet.Cells(row, CELL.FIELD_DESC_COL).Value;
   if( desc == null || desc.length == 0 ){
    desc = '';
   }
   fields[fields.length] = {
     'name':name,
     'type':type,
     'length':length,
     'description': desc
    };

   row++;
  }
  
 }catch(e){
  //例外発生 -> 無視
 }finally{
  try{
   //Excelファイル close
   book.Close();
  }catch(e){}
  try{
   //Excel終了
   xls.Quit(); //きちんとQuitしないとプロセスが残る
   xls = null;
  }catch(e){}
 }
 return fields;
}

/**
 * アンダーバーを除去し、lowerCamelCaseに変換する
 */
function toLowerCamelCase(str){
 var tmp = str.toLowerCase();
 var arr = tmp.split('_');
 var ret = arr[0];
 for(var i=1; i<arr.length; i++){
  ret += arr[i].charAt(0).toUpperCase() + arr[i].slice(1);
 }
 return ret;
}

/**
 * アンダーバーを除去し、UpperCamelCaseに変換する
 */
function toUpperCamelCase(str){
 var tmp = str.toLowerCase();
 var arr = tmp.split('_');
 var ret = '';
 for(var i=0; i<arr.length; i++){
  ret += arr[i].charAt(0).toUpperCase() + arr[i].slice(1);
 }
 return ret;
}

/** JavaDocコメント文字列 出力 */
function javadocString(msg){
 return ['/**',msg,'*/'].join(' ');
}

/** DBMSタイプ→Java型に変換 */
function getType(t){
 var ret = 'String';
 
 if( /VARCHAR/i.test(t) ){
  ret = 'String';
 }else if( /NUMBER/i.test(t) ){
  ret = 'int';
 }else if( /DATE/i.test(t) ){
  ret = 'String';
 }
 
 return ret;
}


(function(){
 for( var i=0; i<XLS_FILES.length; i++ ){
  //Excelファイル読み込み
  var fields = readExcel(XLS_FILES[i]);
  //1つめの要素はテーブル定義
  var tableName = fields[0].name;
  var tableDesc = fields[0].description;
  //結果出力ファイル
  var fileName = tableName + '_' + tableDesc + '.txt';
  WScript.Echo(fileName);
  
  //出力ファイルデータ
  var dat = [];
  
  dat[dat.length] = javadocString(tableDesc);
  dat[dat.length] = 'final public static String TABLE_NAME = "' + tableName + '";';
  dat[dat.length] = '';
  
  //フィールド順の定義
  for( var j=1; j<fields.length; j++ ){
   dat[dat.length] = javadocString(fields[j].description);
   dat[dat.length] = 'final public static int FIELD_' + fields[j].name.toUpperCase() + ' = ' + j + ';';
  }
  dat[dat.length] = '';
  
  //フィールド変数
  for( var j=1; j<fields.length; j++ ){
   dat[dat.length] = javadocString(fields[j].description);
   var type = getType(fields[j].type);
   dat[dat.length] = ['private', type, fields[j].name.toLowerCase()].join(' ') + ';';
  }
  
  //ファイル出力
  var f = fso.CreateTextFile(fileName, true);
  f.WriteLine(dat.join(String.fromCharCode(13) + String.fromCharCode(10)));
  f.Close();
 }
})();

2012/02/10

【shell】 ファイルを指定ファイル数ごとにサブディレクトリに移動する

何年か前に書いたShell Script。
cutコマンドの使い方がすごい強引だったので、アップしてみます。
またどこかで使えるかも・・・


  • ファイルを指定されたディレクトリ以下に移動する
  • ファイル数が指定された数を越えないように、サブディレクトリに分割する


#! /bin/sh
# mv_files.sh
# ファイルを別ディレクトリに移動する
# 指定ファイル数ごとにサブディレクトリを作成する

FILE_NUM=30
TO_DIR=/work/mv_test/to_dir
FROM_DIR=/work/mv_test/from_dir

count=`find ${FROM_DIR} -type f | wc -l`
until [ $count -eq 0 ]; do
 if [ $count -le $FILE_NUM ]; then
  n=$count
 else
  n=$FILE_NUM
 fi
 # フォルダ作成
 dir_name=`date "+%Y%m%d%H%M%S%N"`
 mkdir "${TO_DIR}/${dir_name}"

 echo ${n}

 # ファイル移動
 files=`find ${FROM_DIR} -type f | sort | cut -d "
" -f 1-${n}`
 mv ${files} "${TO_DIR}/${dir_name}"

 count=`find ${FROM_DIR} -type f | wc -l`
done

2012/02/09

【PowerShell】 日時の処理 (get-date, new-timespan)


get-date


DateTimeオブジェクトを作成する。
System.DateTime。
Get-Date [[-date] <DateTime>] [-displayHint {<Date> | <Time> | <DateTime>}]
[-format <string>] [-year <int>] [-month <int>] [-day <int>] [-hour <int>]
[-minute <int>] [-second <int>] [<CommonParameters>]
Get-Date [[-date] <DateTime>] [-displayHint {<Date> | <Time> | <DateTime>}]
[-uFormat <string>] [-year <int>] [-month <int>] [-day <int>] [-hour <int>]
[-minute <int>] [-second <int>] [<CommonParameters>]

  • 来月の日時を取得する
(get-date).AddMonths(1)

  • 30日後を取得
$ts = new-timespan -days 30
(get-date).add($ts)


new-timespan

TimeSpanオブジェクトを作成する。
System.TimeSpan。
New-TimeSpan [[-start] <DateTime>] [[-end] <DateTime>] [<CommonParameters>]
New-TimeSpan [-days <int>] [-hours <int>] [-minutes <int>] [-seconds <int>] [<CommonParameters>]

  • 指定日から今日までの日数を取得する
(new-timespan (get-date -year 2000 -month 4 -day 1)).days

2012/02/04

「新しいタブ」の拡張



先日作成した「新しいタブ」に日時を表示するGoogle Chrome拡張を修正。


  • TwitterのBootstrapが2.0にバージョンアップしていたので、試してみる
  • CSS3のプロパティも使用して、それなりに映える見栄えを目指す



履歴検索機能を追加したものの、イマイチ使い勝手が良くない。
標準の「新しいタブ」に表示されている "よくアクセスするページ" はどうやって取得するんだろう・・・


https://github.com/Kazunori-Kimura/ClockNewTab

2012/01/31

カスタマイズの幅が広がるアプリ - Minimalistic Text

AndroidのWidgetアプリ。

文字で時間や天気、簡単なシステム情報を表示するWidgetを自由に作成、配置できる。

スクリーンショットみたいにかっこ良く文字色やレイアウトを行うのは結構な手間がかかるけど、フォントと文字サイズをいじるだけでもソレナリに良い雰囲気になった。

ホームアプリとかロック画面とか、Androidはいろいろカスタマイズできるけど、チマチマ触ってるとあっという間に時間が過ぎちゃうんだよね。


Minimalistic Text[https://market.android.com/details?id=de.devmil.minimaltext]