2013年12月15日日曜日

Androidのグラフ描画ライブラリを探してみる。

Androidアプリに限らず、ツールを作成しているとグラフが描きたい場面に遭遇することはあるかと思います。
しかしながら、グラフ描画をゼロから作成するなんて簡単ではないです。(少なくとも自分には)

そこで、だれかが開発しているであろうライブラリを探すのですが・・・
探す上で幾つか問題が出てきます。

1. 使いやすいのか?
2. ライセンスは大丈夫か?

など。いろいろなライブラリを紹介しているサイトがあるので一覧を作成しませんが、個人的に使おうと決めたライブラリを紹介。

achartengine なにが良かったのか。
当然ですが、描きたいグラフが描ける。ライセンスが厳しくない(厳しいとか厳しくないとかの次元ではないですが、Apache License 2.0)
あと、設定が細かくできるため使いやすかったです。

公開しているアプリもこれを使いました。

棒グラフと折れ線グラフが同じグラフに表示できたり、複数の折れ線グラフを重ねることができたり。
便利です。

Apache License は以下の2点だけ気をつけました。

1. Google Play の記載情報として、以下の文を載せる。
このソフトウェアは、 Apache 2.0ライセンスで配布されている製作物が含まれています。
2. ソースファイルに以下を追記する。(XXXXXXの箇所は隠しました。)
/*
* Copyright (C) 2013 XXXXXXXXX
*
* 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.
*/

他にもやることあるかもしれないですが、このくらいで。

2013年12月14日土曜日

Androidのアプリ開発におけるStringの注意点

なんとなく普段Javaを書く感覚で開発してたところ、Eclipseに出ていたWarningが気になった。

以下、出力された渓谷
Provides more information about this issue.
Calling String#toLowerCase() or #toUpperCase()
 without specifying an explicit locale is a common
 source of bugs. The reason for that is that those
 methods will use the current locale on the user's
 device, and even though the code appears to work
 correctly when you are developing the app, it will fail
 in some locales. For example, in the Turkish locale,
 the uppercase replacement for i is not I.
If you want the methods to just perform ASCII
 replacement, for example to convert an enum name,
 call String#toUpperCase(Locale.US) instead. If you
 really want to use the current locale, call
 String#toUpperCase(Locale.getDefault()) instead.


詳細メッセージを表示してみた。

URL書いてあったので移動(ここ)。

たぶん、文字列を扱う際に英語以外の言語に注意しろと言っていると思う。
トルコ文字の"i"と”I"は違うんだ!って書いてあった。
他の事例はわからんけど、toUpperCaseとか文字列変換を気軽にやると痛い目に会うよということらしい。
USはたくさん使ってる人いるし、使いやすい。みたいなことが書いてあってすごく適当な仕様だとおもった。

普段使う文には大丈夫なんだろうけど、Locale.USをいつも指定すれば、平気かなぁなんて考えてる。

Warningが減ったので気分はすこしすっきり。

2013年11月23日土曜日

SO_KEEPALIVEの設定はデフォルトで有効になっててほしい

プロセス間で通信を行うアプリケーションを作成した場合、ちょっと考えを怠ると、無通信な状態で応答を待ち続けてしまうことがある。

趣味で作っていたらすぐ直せばいいんだろうけど、そうも行かない場合もある。
そんなとき、ファイアウォールとかプロキシサーバとかが無通信状態のコネクションをさくっと切断してくれるので、一定時間経過すると必ず失敗する状態になってしまう。

一般的に、無通信状態は良くないので、サーバ側が応答無かった場合、リソースの開放の意味を含めてコネクションを切断する機能がOSに備わってたりする。

keepaliveはその無応答状態を検知して接続先に応答確認を行ってくれる。
http://linuxjm.sourceforge.jp/html/LDP_man-pages/man7/tcp.7.html

何度も読んだり、検索したりしてkeepaliveってなんだろうと考えてたんだけど
少なくとも無通信状態を検出してコネクションを切断する奴らからコネクションを守る機能ではないと思った。

でも、そういう使い方もできるなぁと。
ちなみに、ソケット作成時にSO_KEEPALIVEをオプションとして有効にしないとこの機能は使われないので、誤ってサーバが無応答になったらクライアントも無応答に。。悲惨だ。。

2013年11月17日日曜日

SSID毎の通信量を確認したいため、Androidアプリを作りました。

GL04PにOCNのSIMを指して一ヶ月くらいが経過しました。
通信量は足りていると思うのですが、本当に十分かどうかを確認したいことと、
利用の抑制のため、通信量を確認したいと思ってました。

OCNのエントリーDでは、どこを探しても現在の通信量を表示するページはありませんでした。

そこで、こんなアプリを作成してみました。
あくまで通信量の目安ですが、通信量を把握することができます。

突貫で作成したため、昨日は殆ど無いですが、一月分の合計が見れればいいかなと。

Wi-Fi通信量 監視ツール

モバイルデータ通信をOFFにしてパケット代を節約しようとしている人には通信量の確認としてはいいのではと思います。


追加:2013年12月22日
FileDir.comに追加されたと連絡がありました。海外のサイトなので日本にはあまり関係ないですが、掲載していただいたのでリンクを張ります。
Download Wi-Fi traffic counter tool / Android

2013年11月12日火曜日

OCN モバイル ONEの通信量を知りたい。

GL04PとOCNのSIMカードを利用してから3週間くらい経過しました。
使用感覚としては、容量の上限である1日30MBを超えたあたりから速度が落ちるためか、だいぶ待たされる感じがします。

ただし、通信状況が悪いためか、30MBを超えたためかは判断が難しく、どちらの影響でWebページの読み込みが遅いのかはわかっていません。

Wi-FiのSSID毎の使用量を確認することができれば、自分に必要な通信量が見えてくるかもしれないですが。。。
1ヶ月で1GBあればいいのか、1日30MBあればいいのか。データがないので判断できません。

個人的な感想ですが、携帯のキャリアへ支払うパケット定額の料金を支払うくらいなら、ちょっとくらい通信が不便でも十分使えると思ってます。

気になるのは、どのプランが自分にとって最適なのか。です。
しばらくは、1日30MBプランで十分かと思ってます。

ちなみに、十分なデータは取ってませんが、速度制限は30mbを超えたら即座に200kbpsではないようです。
超えたばかりの時は、600kbps程でしたが、40mbを超えた頃に200kbpsとなってました。

2013年10月18日金曜日

GL04PにOCN モバイル ONEのSIMカードを挿入してみた

普段の通勤圏であれば、WiMaxで問題なかったけれどちょっと出かけたり、デパートやショッピングモール内に入ると電波が届かなくなるのに不満がつのったため、OCNのモバイルONEに乗り換えてみた。

利用した端末は以下
・GL04P (イーモバイル)

GL04Pの設定は以下のページを参考にしました。
※APNの設定部分だけ、モバイルONE申し込み完了時に表示されるAPNに読み替えれば問題なく接続出来ました。

http://tech.support.ntt.com/ocn/mobile/em_entry_lte/gl04p/setup_windows.html

まだ設定したばかりですが、WiMaxに比べると速度は落ちる印象があります。
#正確な速度測定はしていません。あくまで体感です。

端末は少し大きめで、スマートフォンと同じくらいの重さに感じます。
ただ、通信をしなければスリープしてくれるというので、カバンにしまったままにできるのではと期待しています。
WiMaxの時は端末が対応していなかったので、スリープモードからの解除は必ずボタンを押す必要がありました。
そのため、いつもポケットに入れてました。

GL04Pはポケットに入れっぱなしにするには大きすぎる気がします。

2013年9月23日月曜日

ペヤング辛口 食べてみた

夜食に困って近隣のドラックストアをふらふらしていたところ、ペヤングの辛口を発見
今まで、普通のペヤングしか食べたことがなかったので興味本位で購入。

http://www.peyoung.co.jp/item/product/8

実際に食べてみました。

感想としては、正直ここまで辛いとは思ってませんでした。
あまりの辛さに口を水でゆすぎましたが対処できず、インターネットで検索して牛乳を飲むと良いというので試したところ驚くほど辛さが引いていきました。

完全には辛さが引きませんでしたが、耐えられる程度にはなりました(汗)


2013年9月17日火曜日

iMac 2012 と ロジテックDVD( LDR-PMG8U3LSV)を接続してみた

iMacにDVDドライブが欲しかったので、安めのドライブとしてLogitec社のDVDドライブを購入しました。
接続してみたところ、正常に動作せずまともにDVD再生などできませんでした。


環境
OS : OS X 10.8.5
筐体:  iMac 27 inch ( 2012 )

接続対象
DVDドライブ: Logitec社 LDR-PMG8U3LSV


試したこと
まず、バスパワーで動作するとの事だったので、DVDドライブとiMacをUSBのみで接続しました。
Mac接続後は軽快に動作しているように見えましたが、「故障箇所をスキップします」のようなメッセージが頻繁に画面に表示され、しまいにはDVD Player(Mac標準のソフト)が強制終了しました。

なんどかDVDを変更し、試してみましたがうまくいかないため、Windowsへ接続(詳細は省略)
Windowsではなんの問題もなくバスパワー単体で動作するため、DVDドライブの初期不良の疑いを排除しました。
また、バスパワーだけで動作することから、iMacからの供給電力が不足しているのではないかと推測。

純正ではないですが、BUFFALO製の外部電源供給ACアダプタ AC-DC5-BKを接続した状態で再度挑戦。

しかしながら、状況は改善せず。

旧式のMacbookに上記アダプタを接続した状態では、動作しているように見えたので、iMacを疑い、Appleのサポートへ連絡。

いっとお決まりの手順であろう、以下の内容を実施させられるも、効果なし。
・SMCのリセット
・起動時にシフトキーを押した状態での設定リセット
・OS再インストール

結局Mac純正の USB SuperDriveを購入することに。
現在動作確認中ですが、あれだけ「故障」とか表示されてたDVDがなんの問題もなく動作している。

なんか悔しい。

2013年8月19日月曜日

ScheduledExecutorServiceが停止した。

なんの前触れもなく、ScheduledExecutorServiceが停止してしまった。
実行のため、invokeしていたThreadクラスに問題があったのかどうか調べたけど、そうでも無さそう。

そんなとき、ScheduledExecutorServiceが動かなくなるという現象について書かれた記事を見つけた。

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7139684

どうやらスレッドを起動するために利用している OSレベルの処理でシグナル受信に失敗し、起動するはずのスレッドが起動しないままになってしまっているようだ。
しかも、一度失敗すると二度と起動しないという。。。。。


みたところ、回避策は提示されていないので、この現象にはまったら、プロセスの再起動だろうか。
shutdown()と、submit()で、復旧できるといいんだけど。

2013年8月17日土曜日

new Date().getTime() と System.currentTimeMillis() どちらが早いのか を調べてみた

先ほどの投稿から、ちょっと気になったので調べてみた。
大したことではないですけど、時間を取得したり計測するのに、よく使うんじゃないかと思いますが、
どちらが高速なのか。が気になって調べてみました。

結果から言うと、System.currentTimeMillis()の方が倍高速です。
どちらも1000000回実行した時の合計時間です。

new Date().getTime()         188ms
System.currentTimeMillis()     91ms

インスタンス生成に時間がかかるのでしょうかね。
1000000回なので、どっちを使おうがあまり関係ない位だと思いますが、どちらかというと軽いのでSystem.currentTimeMills()を使ったほうが余計なことしないのでいいかなと。思いました。

計測環境を記載していないのは、実効速度を調べたかったのではなく、どちらが早いかを確認したかっただけなので載せてないです。マシンによって差があるというのであれば考えますが.....
OSはWindows Vistaです。

ソースは汚いですが、以下です。
import java.util.Arrays;
import java.util.Date;
import java.util.Iterator;
public class PerformanceSample {
/**
* @param args
*/
public static void main(String[] args) {
ExecuterIf process = null;
// NewDate
process = new NewDate();
PerformanceMesure.execute(process);
// currentTimeMillis
process = new SystemCurrent();
PerformanceMesure.execute(process);
}
}
class NewDate implements ExecuterIf{
@Override
public void exec(){
long time = new Date().getTime();
}
}
class SystemCurrent implements ExecuterIf{
@Override
public void exec(){
long time = System.currentTimeMillis();
}
}
interface ExecuterIf{
public void exec();
}
class PerformanceMesure{
public static void execute(ExecuterIf process){
long start = 0L;
long end = 0L;
long elapse = 0L;
start = System.currentTimeMillis();
for(int m = 0 ; m  < 1000000; m ++)
process.exec();
end = System.currentTimeMillis();
elapse = end - start;
System.out.println(elapse + "ms");
}
}

Exceptionを利用したループのハンドリング性能

Effective Java の Item57 にあるwhileループのやってはいけない例について調べてみました。
たぶん、こんな使い方する人はいないんだと思いますが、悪いことしかないってことを確かめたかったので。

調べたのは性能です。ソースを見るとわかりますが、エラーなのかループの終了なのか判断できないため、使う人はいないと思います。

以下の2つの性能を比較しました。
例1)
// Horrible abuse of exceptions. Don't ever do this!
try{
  int i = 0;
  while(true)
    range[i++].climb();
}catch{ArrayIndexOutOfBoundsException e{
}
例2)
int i = 0;
while(range. length > i)
  range[i++].climb();
配列のサイズは100、試行回数は1万回。累積時間(ms)を計測した結果です。

例1  230ms
例2  2ms

こんなに差があるとは思ってなかったですが、100倍違います。

EffectiveJavaでは、現在のJVMを利用した場合は遅い。とか書いてありましたが、昔は早かったのでしょうか。
そうだとすると、悪い書き方をしたソースがあるかもしれないですよね....
この例だけでは言えませんが、正当な作り方をしておくと、のちのち性能が上がるかも知れない。
ということでしょうか。
その場しのぎのコーディングはやめようと思います。

2013年7月18日木曜日

Tomcatのsharedローダのクラスを監視する Java Intaractive Profiler(JIP)の備忘録

最近、プロファイラを利用してアプリの挙動の確認を行った。hprofでなく、JIPを利用しました。
利用したのは現在(2013年7月)のバージョン(1.2)です。

使い方は色々なページで説明していたり、ドキュメントが付属しているのでなんとなく読めばわかりますが、ちょっとわからなかったことを備忘録として書いておきます。

参考:http://d.hatena.ne.jp/goking/20101125/p1


  • Tomcatのアプリと、sharedloaderに指定したライブラリをプロファイルする
どうしても見つけられなかったので、書き残しておきます。

通常、Webアプリのプロファイルをする場合は、プロファイラとしてwebapp.profile.propertiesを指定しますが、こいつを少し編集します。

もともとの内容の一部

#
# Class Loader filters for different runtine environments
# (The system will cycle through these until it finds one that
# can filter in the current environment)
#
ClassLoaderFilter.1=com.mentorgen.tools.profile.instrument.clfilter.WebAppClassLoaderFilter
ClassLoaderFilter.2=com.mentorgen.tools.profile.instrument.clfilter.StandardClassLoaderFilter


 書きなおした結果

#
# Class Loader filters for different runtine environments
# (The system will cycle through these until it finds one that
# can filter in the current environment)
#
ClassLoaderFilter.1=com.mentorgen.tools.profile.instrument.clfilter.TomcatInternalClassLoaderFilter
ClassLoaderFilter.2=com.mentorgen.tools.profile.instrument.clfilter.StandardClassLoaderFilter

 ClassLoaderFilter.1 をTomcatInternalClassLoaderFilterに変えます。これで、sharedloaderのクラスもプロファイル対象となりました。

あとは、excludeの項目に、見たくないパッケージを記載しておけば、ごちゃごちゃしなくなります。

Javaネイティブのクラスをプロファイル対象にできないかどうかは探し中です。
見つかるのかわからないですが....

他にもいくつかプロファイラがありますが、どうやって使うのかはわかりません。
http://www.java2v.com/Open-Source/Java-Document/Profiler/JIP/com.mentorgen.tools.profile.instrument.clfilter.htm

もうひとつついでに。
ダウンロード先のSourceForgeでは、最初あやまってjip-src-1.2.zipをダウンロードしました。
間違ってはいないんですが、JipViewerが見つかりませんでした。
jip-1.2.zipをダウンロードしたらちゃんとありました。

http://sourceforge.net/projects/jiprof/files/jip/1.2/



2013年5月7日火曜日

Softbankスマートフォン サービス開発支援サイトのサンプルが動かない

ARに興味があるものの、ゼロからの作成は難しいと感じたため、サンプル探し。
Softbankが公開している支援サイトのコードを流用しようと思った。

参考にしようとしたサイトは以下
第10回 ARゲームを作ってみよう(2)

サンプルコードをダウンロードして、実行してみたところ、文字入力はできるが、位置情報の登録ができなかった。

スマートフォンのGPSは有効なっていることを確認し、再度実行したが位置情報が取得できないため
といって動いてくれない。

実行端末:003SH
OSバージョン:2.3.4
カーネルバージョン:2.5.35.7-perf

ざっと探してみたけど、動かないと言っているサイトが見当たらないので探し方が悪いか、そもそもあまり参考にされていないか、動かないのは私だけかの3つくらいが原因かと思い、自分で調べようかと思った。


なぜアプリが動かないか。エラーメッセージからわかることは、位置情報の取得がうまく動いていないようだ。
ソースからわかるように、位置情報(geomagneticField)がnullの場合は描画が全く動かない。
さらに、「位置情報の取得ができません」というメッセージが画面に表示されるようになる。

動かない理由を調べるために、ログ情報を出力させてみた。
ここで、わかったことは、LocationListnerインタフェースを実装した箇所が全く動作していないこと。
これがどういうことなのかは調査中

1点わかったこと

以下の端末だと動作する。ただ、動作可能なバージョンが2.2以上となっているので、2.3.4だから動かないというわけではないと思う。

実行端末:101F
OSバージョン:4.0.4

さて・・・答えは見つかるのだろうか・・・

※1点きになること、003SHは機種変後の余った端末なのですが、GPS情報が正しく取得できていないような気がします。機能制限解除はしたつもりなのですが、GPSは対象外なんでしょうかね。

2013年4月25日木曜日

log4j 1.2 の圧縮指定について

Log4jの記事をちらちら見てますが、日本語のページでは圧縮指定に関する記事は大体XMLを
利用したものしか載っていないので少し探してみた。

以下は英語ですが、圧縮設定方法が書いてある。
log4j 1.2.15以降で利用可能みたいです。

I'm trying to get org.apache.log4j.rolling.RollingFileAppender from the log4j extras companion working, since the documentation suggests this is best for production environments.
I have both the main log4J library (log4j-1.2.15.jar) and the log4j extras library (apache-log4j-extras-1.1.jar) on the classpath.
I have the following configuration for the appender in the log4j.properties file:
### SOAP Request Appender
log4j.appender.request=org.apache.log4j.rolling.RollingFileAppender
log4j.appender.request.File=SOAPmessages.log
log4j.appender.request.RollingPolicy=org.apache.log4j.rolling.TimeBasedRollingPolicy
log4j.appender.request.RollingPolicy.ActiveFileName =SOAPmessages-%d.log
log4j.appender.request.RollingPolicy.FileNamePattern=SOAPmessages-%d.log.zip
log4j.appender.request.layout = org.apache.log4j.PatternLayout
log4j.appender.request.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

参考:http://stackoverflow.com/questions/5117758/configuring-rollingfileappender-in-log4j

ログなんて何かあった時にしか見ない運用の場合は、圧縮しない理由なんかないんじゃないかと
思います。
なぜ、ローテーションは勝手に圧縮する機能にはなってくれないのだろうか。

2013年4月14日日曜日

CalendarContract を利用したイベントのタイムゾーンについて

取得したイベントのタイムゾーンが頭のなかで整理できなかったので書きだしてみる。

終日のイベントを取り出したところ、タイムゾーンはUTCだった。
日時データは 開始はイベント当日の09:00。そして、終了日時は、次の日の 09:00だった。


Andoroid のリファレンスには、書き込む際、終日のイベントはUTCで記載しなければならない。と書かれている。

If allDay is set to 1 eventTimezone must be TIMEZONE_UTC and the time must correspond to a midnight boundary.

次に、時間指定のイベントを取得。
タイムゾーンは Asia/Tokyo。イベントの日時はJSTでカレンダー記載通りに取得できている。

Googleカレンダーでは、終日は朝9時から次の日の9時までということなんだろうか。
しかし、なんで書き込みがUTCなんだろう・・・。

終日データの9:00ってどこから来るのだろうか。
カレンダーを記載するときに、終日。とした場合には、UTCで記載する。
多分この時、UTC時刻で00:00~次の日の00:00って書くんだろうな。

それで、取り出すときに、UTCで00:00だから・・・ +9で、9:00となる?
もしそうなら。。。格納するときもタイムゾーン指定でいいんじゃないかな・・とおもったり思わなかったり。

UTCから + の方にタイムゾーンがある場合、 UTCで当日の00:00を指せば、UTCと同じ日付になるけど - のタイムゾーンだったら。。UTCで00:00ってことは前日になってしまうのでは?

それとも、UTCの00:00を書き込むのが間違いで、JSTの00:00をUTCに変換して格納するとか?
そしたらGoogleカレンダーの作りこみに問題があることに。。。
そんなわけはないだろうと思う。。

java.util.Dateの仕様の勘違いかな。(私の)
Date.getTime()はUTCの経過時刻を返却する仕組みとなっている。
Dateインスタンス生成のときは、GMTの経過時刻を渡す仕組み。
当然、気を利かせて現在のロケールに変換してくれるのだから、UTCで経過時刻を渡せば、
+9してくれるので、00:00ではなく、09:00となる。

こうやって考えると、納得。少しスッキリしたかも。


勝手に納得してても、あとで忘れるのでメモ。


■整理できたこと

  • java.util.Date は UTC を基準とした日付を扱うクラス。ただし、自動でJavaVMの動作するタイムゾーンに合わせるので、JSTに変換される。
  • CalendarContractで取得するイベントには次の2種類がある。
    • 時間指定のイベント:格納するデータはJavaVMの動作するTimeZone。従って日本ではJSTとなる。
    • 終日のイベント:格納するデータはUTCで時刻を指定する必要がある。

■今日、混乱していたこと
  • 終日のイベントの日付を java.util.Date クラスに渡したところ、 +9時間 で表示された。原因はUTCの00:00時刻を渡したため、JSTに変換された。UTCを渡すつもりなら Timezoneのオフセットを考慮する必要がある(TimeZone#getRawOffset()など)。

間違っていなければいいんだけど・・・





2013年4月13日土曜日

AndroidのCursorLoaderのコンストラクタ引数

用語が頭のなかで結びつかないので、知っている用語に置き換えてみる。



public CursorLoader (Context context, Uri uri, String[] projection, String selection, String[] selectionArgs, StringsortOrder)


  • Context : 知っているもの該当なし。Activityを渡す。
  • Uri : 接続先
  • projection : SQLのカラム指定
  • selection : SQLのWHERE句
  • selectionArgs : selectionに?を使った場合に、指定する(SQLのPreparedStatmentみたいな使い方)
  • sortOder : ソート順

置き換えてみたけど、全部ここに書いてあった。。。

汚い日本語に変換しただけでした。

2013年2月10日日曜日

Singltonは何をつかう?

Effective Java item3のSingltonについて
publicなstatic領域を参照させる方法とenumなどが紹介されている。
個人的には、どっちでもいいかもしれないと思っているけれどどうなんだろうか。

Factory型のSingltonもいいとおもうんだけどな。

状況により使い分けるべきか、それとも推奨されるままにenumか。。。。