Hatena::ブログ(Diary)

メモ書き

2013-04-04

GSonでDate型をパースする際にLocaleが関連してエラーがでる

Android 4.0.3

GSon 2.2.2


GSonを使ってJSON形式のデータをパースする際エラーになってしまった。

自分の端末では問題にはならないのに、

職場の韓国の方の携帯ではエラーが発生する。


よくよく調べて行ったら、

AndroidのLocaleの設定によって、

DateFormatが異なってしまうためにString⇒Date変換時にエラーになってしまうことが分かった。

つまり、

class myClass{

          private Date idate;

          private int id;

          /**

          * @return the idate

          */

          public Date getIdate() {

                    return idate;

          }

          /**

          * @param idate the idate to set

          */

          public void setIdate(Date idate) {

                    this.idate = idate;

          }

}


String input = "{"

          + "\"idate\":\"2013/04/04 11:11:11\","

          + "\"id\":\"1\""

          + "}";

myClass my = new Gson().fromJson(input, myClass.class);

Log.d("TAG", my.getIdate().toLocaleString());

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

myClass my = new Gson().fromJson(input, myClass.class);

ここでエラーが発生してしまう。

対処方法として、

Gson gson = new GsonBuilder().setDateFormat("yyyy/MM/dd HH:mm:ss").create();

myClass my = gson.fromJson(input, myClass.class);

として、DateFormatを定義しておけば、AndroidのLocaleが変更されても、

きちんとパースしてくれることを確認した。

2013-03-09

GridViewのCellの中身を縦横比を画面に合わせて固定にする

GridViewを画面サイズにあわせつつ、

中身のCellを正方形にして隙間なく表示させたかった。

(マルチデバイスにも対応させたいので)

ただ、GridViewはViewGroupから継承しているので、

中身のView次第でGridViewの挙動が決まってしまう。

つまり、

numColumnsで列の数を決めて単純に行おうとすると、

横幅は画面にそって決めてくれるのだけれども、

縦幅はViewで取得した値そのままが表示されるので、思ったとおりの表示にはならない。

なので、

GetViewで正方形のViewを作ってあげれば、上記の問題にも対応できるなと

考えたのでやってみた。

@Override

public View getView(int position, View convertView, ViewGroup parent) {

     if (convertView == null) {

          LayoutInflater inflater = LayoutInflater.from(context);

          convertView = inflater.inflate(R.layout.list_row, null);

          // ウィンドウマネージャインスタンス取得

          WindowManager wm = (WindowManager)getSystemService(WINDOW_SERVICE);

          // ディスプレイインスタンス生成

          Display disp = wm.getDefaultDisplay();

          String width = "Width = " + disp.getWidth();

          String height = "Height = " + disp.getHeight();                   

          //widthの幅がわかったので、ここでは5列の例

          convertView.setWidth(width/5);

          convertView.setHeight(height/5);

     }

     //以下略

     return convertView;

}


こんな感じで実現できた。

StackOverFlowなんかを見ると、Custom View でonMeasure()をoverrideしてやればいいよー。

なんてことがあって、これもいいなあと。

http://stackoverflow.com/questions/6557516/making-grid-view-items-square

2013-01-25

NFC機能をつかった入室・退室管理アプリ

AndroidのNFC機能を使った

入室・退室アプリを公開してみました。

簡易的な使い方ならタイムレコーダー替わりにも使えるので、

お金出してタイムレコーダー買うよりもコスト的にいいかと。

【NFC 入室・退室管理】

https://play.google.com/store/apps/details?id=jp.ne.interpia.checkin&feature=search_result#?t=W251bGwsMSwyLDEsImpwLm5lLmludGVycGlhLmNoZWNraW4iXQ..


【条件】

・NFC機能のついているAndroid

・NFCの読み取り機能をONにしておくこと

f:id:tetsu831:20130125103040p:image:w360



【使い方(設定編)】

1.メイン画面から「メニュー」⇒「設定」を押すとこんな画像が表示される。

f:id:tetsu831:20130125103043p:image:w360

・Gmail管理にチェックを入れる

・Gmailアドレスの設定から有効なGmailアドレスを入力する。

 (本アプリ以外に使用しません)

・Gmailパスワードを入力する

・送信先アドレスの入力する。データを送りたい送信先アドレスを入力して下さい。

・メール送信(入室・退室ログ)を実行すると、入室・退室ログが送信先アドレスに

 メールが送信されます。

・メール送信(登録情報)を実行すると、登録情報が送信先アドレスに

 メールが送信されます。

・DB情報送信を実行すると、DB(SQLite)のファイルが添付され送信先アドレスに

 メールが送信されます。

・入室・退室ログ初期化を実行すると、入室・退室ログが初期化されます。

 初期化する前にメールにて送信しておくことをお勧めします。

・登録情報初期化を実行すると、登録情報が初期化されます。

 初期化する前にメールにて送信しておくことをお勧めします。


【使い方(登録)】

1.メイン画面から「メニュー」⇒「登録」を押すとこんな画像が表示される。

f:id:tetsu831:20130125103038p:image:w360


2.手持ちのNFCカード(Suica、NFC付携帯など)を

 Androidにかざす。


3.そうすると、NFCカードのIDM情報をキーに名前・カナ・備考が表示される。

 ただし、新規の場合は空欄にて表示される。


4.名前・カナ・備考に入力して、

「登録」ボタンを実行すると、NFCカード情報に名前・カナ・備考が紐づけされる。



【使い方(入室・退室)】

1.NFCカード(Suica、NFC付携帯など)を

 Androidにかざす。こんな画像が表示される。

f:id:tetsu831:20130125103042p:image:w360


2.NFCカードが登録されている場合は、

 登録されている内容で、名前・カナ・備考が表示される。

 NFCカードが登録されていない場合は、

 「未登録のカードです」とエラー表記される。


3.NFCカードが登録されている場合は、「入室」・「退室」・「キャンセル」

 の各ボタンが有効になっています。

 入室処理をしたい場合は「入室」ボタンを押す。

 退室処理をしたい場合は「退室」ボタンを押す。

 キャンセルをしたい場合は「キャンセル」ボタンを押す。

 入室・退室を選択した場合は情報が保存されます。


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


有料にしてみたのは、

有料の方がやる気がでそうだから。

(無料だと、「どうせ無料だしー。」みたいな感じがあるので)

2012-12-12

URIから画像ファイル先を取得する。

はまりました。

URIから画像取得するだけだから楽ちんだろー。

と思っていたら、失敗して時間ばかりかかってしまったのでメモ。


最初にWEBの情報をベースに用意したのが以下のコード

/**

* UriからPathへの変換処理

* @param uri

* @return String

*/

public static String getPath(Context context, Uri uri) {

ContentResolver contentResolver = context.getContentResolver();

String[] columns = { MediaStore.Images.Media.DATA };

Cursor cursor = contentResolver.query(uri, columns, null, null, null);

Log.d(LOG_TAG, "uri.toString():" + uri.toString());

if (cursor == null) {

cursor = contentResolver.query(uri, columns, null, null, null);

Log.d(LOG_TAG, "uri.getPath(): " + uri.getPath());

if (null == cursor){

Log.e(LOG_TAG, "cursor is null");

}

}

cursor.moveToFirst();

String path = cursor.getString(0);

Log.d(LOG_TAG, "getPath:path:" + path);

cursor.close();

return path;

}

ギャラリーから取得したURI

ならば問題はなくPathを取得できる。

しかし、画像編集用のライブラリーであるAviaryからもどってくるURIを使用して

pathが取得しようとするとエラーになる。

http://www.aviary.com/

LogCat上ではこんな感じ

⇒ギャラリーから

12-12 15:03:54.600 D ImageUtilities( 8574) uri.toString():content://media/external/images/media/7951

12-12 15:03:54.600 D ImageUtilities( 8574) getPath:path:/mnt/sdcard/Pictures/aviary/aviary_1354264866459.jpg

⇒Aviaryから

12-12 15:05:30.420 D ImageUtilities( 8574) uri.toString():file:///mnt/sdcard/Pictures/NMM3/NMM3_1355292322370.jpg

12-12 15:05:30.420 D ImageUtilities( 8574) uri.getPath(): /mnt/sdcard/Pictures/NMM3/NMM3_1355292322370.jpg

12-12 15:05:30.420 E ImageUtilities( 8574) cursor is null

つまり、ここでなにが分かるかというと、

uriで取得しているデータのスキーマが違うために

上記ソースではfile:///〜始まる内容に対応できず、

cursorを生成しても、nullになってしまうのが問題。

と、いうわけでuriのスキーマから処理する内容を変えてあげるように

すればいい。

/**

* UriからPathへの変換処理

* Uriのscheme()から

* context://

* file://

* を判断して、処理する内容を変える。

* @param uri

* @return String

*/

public static String getPathFromUri(Context context, Uri uri) {

String filePath = null;

Log.d(LOG_TAG, "uri :" +uri);

if (uri !=null && "content".equals(uri.getScheme())) {

Cursor cursor = context.getContentResolver().query(uri, new String[] { android.provider.MediaStore.Images.ImageColumns.DATA }, null, null, null);

cursor.moveToFirst();

filePath = cursor.getString(0);

cursor.close();

}else{

filePath = uri.getPath();

}

return filePath;

}

これでうまくできた。

取得するuriのスキーマが違っても大丈夫。

2012-12-05

AndroidからParseを使ってみる

[Parse]を用いた処理を書いてみる

https://www.parse.com/

BaaS(Baceend as a Service)サービスの一つ。

気になっていたので使ってみた。

Parseサイトでアカウントを作成する。

クイックスタートガイドを見ながらAndroidのアプリを生成する

https://www.parse.com/apps/quickstart


アプリを起動して、オブジェクトを投げると

DashBoardにオブジェクトが保存されている!

以上

なにか書くまでもなく、

ほんとアッサリできるのでちょっとしたデータ共有をするのであればおススメ。

無料プランは月に100万リクエスト、1GBなので、

画像とか扱うのはちょっとつらいかな。

(オブジェクトに画像ファイルを送れば、画像ファイルも保存される)