2013年6月28日金曜日

Android搭載端末の調査に便利なサイト まとめ

Androidアプリの作成では様々な端末への対応を考慮しなければなりません。
現在どのような端末が出てるのか、調査に便利なサイトをまとめてみました。

まずはこちら、Google公式?のAndroid Device Galleryです。
かなりの数の端末が登録されていて国やキャリア、OS等の条件で検索できます。かなりの数なのでGoogle Playストアで承認されている端末が全部あるのかなと思いましたが、そこまでではないようです。
端末ごとにCPU・Camera・Display・OS Version・Storage and Memory・Battery・Connectivity等のかなり詳しい情報も見ることが出来ます。
Android Device Gallery
http://www.android.com/devices/

次はこちらWikipediaのAndroid端末一覧ページです。
2009年のHT-03Aから始まって、発売日順にメーカー・形状・OSバージョン・キャリア等を一覧で見ることが出来ます。
Android端末一覧
http://ja.wikipedia.org/wiki/Android%E7%AB%AF%E6%9C%AB%E4%B8%80%E8%A6%A7

次はスマートフォンデータベースです。
スマートフォン231機種のスペックをキャリア・メーカー・OSバージョン・性能・機能等の条件を指定して一覧で見ることが出来ます。
スマートフォンデータベース
http://smartphone.ultra-zone.net/

次は国内主要キャリアの端末を一覧でまとめているDevelopers AppKitBoxのサイトです。
キャリアごとにメーカー・OSバージョン・解像度・CPU等を一覧で見ることが出来ます。
Developers AppKitBox
Docomo
http://appkitbox.com/knowledge/android/2012/11/12/docomo-smartphone
AU
http://appkitbox.com/knowledge/android/2012/11/12/au-smartphone
Softbank
http://appkitbox.com/knowledge/android/2012/11/12/sb-smartphone
その他
http://appkitbox.com/knowledge/android/2012/11/12/other-smartphone

最後は主に画面のサイズ、解像度等を一覧で見ることが出来るSCREEN SIZ.ESというサイトです。
こちらの特徴として、独自の方法で計算された指標ではありますがpopularityとういう項目で端末の人気度を見ることが出来ます。
SCREEN SIZ.ES
http://screensiz.es/

以上参考までに。

2013年6月26日水曜日

間取りー図が5万ダウンロードを達成しましたー

このたび間取りー図が5万ダウンロードを達成しましたー。
これもひとえにダウンロードしていただいたユーザーの皆様のおかげです。
公開開始が2012年11月6日でしたので、約7か月半での達成となりました。


この間10回程のバージョンアップを行いました。ユーザーからの不具合報告や要望はありがたい限りです。
国別でみると日本が66.84%、アメリカ7.4%、他25.76%と意外に海外の方も利用して頂いているようです。Feet単位に対応してほしいなどの要望もあったのでVersion 1.2.0で対応したりもしました。

今後も機能追加や改善に励みたいと思いますので、よろしくお願いいたします。

2013年6月25日火曜日

dimen.xmlからのdip指定によるgetDimensionの落とし穴

使い方を間違っているだけなのに落とし穴と書いてると怒られそうですが、昨日修正を公開した間取りー図での不具合は、リソースのdimen.xmlでdip単位で書いてある値をSurfaceViewのボタンの大きさ指定に使っているのですが、ここで間違った計算をしているのが原因でした。

最近間取りー図のユーザーレビューで
・ボタンが見切れてほとんど使えない
・5インチフルHDの画面なんだけど、各種ボタン(+-や反転等の)の大きさが極端に合ってない
という報告が上がってきていて、ボタンはdipの値から計算してサイズ設定しているからそんなはずはないんだけどなぁと思いながら、対象の実機で確認してみると本来は


こうなるべきところが
と報告と同じくえらいでかいサイズになってしまっていました。
原因を探ってみたところ、どうやらxxhdpi(超高解像度)の端末で、このような現象になっている模様。
リソースでの指定は
  <dimen name="button_width">48dp</dimen>

こんな感じ、この値をプログラムでは
int bw = (int)(context.getResources().getDimension(R.dimen.button_width) * context.getResources().getDisplayMetrics().density + 0.5f);

このように値を取得・計算して、最終的にピクセル単位にしてボタンを描画していました。
要はこの計算が間違っていたのですが、どうやらgetDimensionはanyDensityがtrueの場合DisplayMetricsで単位変換されるということのようです。

つまり私はgetDimensionですでに単位変換されている値を、更に単位変換してしまっているので、xxhdpiの場合getDimensionでもとの3倍、それをさらに3倍しているということでした。
あまりこのような使い方をしてる人はいないかもしれませんが、お気を付けて…

参考:【教えてください】TextView等のテキストサイズについて
参考:Converting dp units to pixel units

2013年6月24日月曜日

"間取りー図"のバージョンアップを公開しました。

"間取りー図"、"間取りー図 Pro"のバージョン 1.2.2を公開しました。
修正点は一部の端末(Xperia Z、Garaxy S4等)において図形操作ボタンが大きすぎて、画面に表示しきれない問題を修正しました。
対象の方々にご迷惑をおかけしましたこと、この場を借りてお詫び申し上げます。

2013年6月21日金曜日

自作ライブラリ-SurfaceViewで画像の数字を表示

Androidアプリ・ゲームを作るときに、スコアやパラメータなど数字を表示したい場合が結構あります。
こんなときCanvas#drawText()で済めばいいんですが、見た目にこだわりたいときは画像を使う他ありません。 
やることは数字の画像を0から9まで用意して各桁の数字に合わせて位置を決めて描画するというだけですが、何回もでてくるので汎用的なクラスにしてしまったほうがいいかなということで作ってみました。 
まず0から9までの画像を用意。


表示用のクラスはこんな感じ

public class CvsNumber {
    public Rect res;
    public Bitmap[] images = null;
    public int number = 0;
    public int digit = 3;
    public boolean zerofill = false;
    public int top;
    public int left;
    public int width;
    public int height;
    public Paint paint = new Paint();
    private Rect src;

    public CvsNumber(int id, Context context, int[] resources) {
        images = new Bitmap[10];
        //0から9の画像をセット
        for (int i = 0; i < 10; i++) {
            images[i] = BitmapFactory.decodeResource(context.getResources(), resources[i]);
        }
        //1つ目の画像の大きさを取っておく
        src = new Rect(0, 0, images[0].getWidth(), images[0].getHeight());
    }

    public void draw(Canvas canvas) {
        int r = left + width; //描画範囲の右端
        int w = width / digit; //1桁当たりの描画幅
        int h = (w * images[0].getHeight()) / images[0].getWidth(); //1桁当たりの数字の描画高さ
        int t = top + ((height - h) / 2); //描画開始高さ
        int s = number % 10; //1の位の数字
        //1の位を描画
        canvas.drawBitmap(images[s], src, new Rect(r - (w * 1), t, r, t + h), paint);
        //digitで指定した位まで描画
        for (int i = 1; i < digit; i++) {
            if (zerofill || String.valueOf(number).length() > i) {
                s = (number / (int)(Math.pow(10, i))) % 10;
                canvas.drawBitmap(images[s], src, new Rect(r - (w * (i + 1)), t, r - (w * i), t + h), paint);
            }
        }
    }
}

表示結果はこんな感じ。
与えるパラメータは描画位置のtop,left,width,heightとnumber(値),digit(桁数),zerofill(0埋め)です。
 
※四角い枠は指定した描画範囲をわかりやすいように表示してます。

一度作っておけば画像を差し替えれば、いろんなパターンで利用できて捗ること間違いなしです。
SurfaceViewに限らず自作Viewでも利用可能ですね。 

2013年6月19日水曜日

Androidアプリでデータをファイルで保存したい

Androidアプリでデータをファイルに保存したいことがあります。
ものによってはデータベースを使う方がいい場合もありますが、単体で出力したい場合に便利なのがシリアライズ。 データを1つのSerializableなクラスインスタンスにまとめておけばObjectOutputStream.writeObjectで簡単にファイルにすることが出来ます。
シリアライズのすごいところはそのクラスのフィールドがSerializableなクラスで構成されている場合には、出力コードを何にも書かなくていいんです。
たとえSerializableではないクラスがあったとしても、そこだけ自分で出力するかSerializableクラスに置き換えるだけでいいんです。

//データクラス
class S implements Serializable {
    private static final long serialVersionUID = 1L;
    public int id;
    public String name;
    public boolean visible;
    public S(int id) {
        this.id = id;
    }
}
//出力
S data = new S(1);
FileOutputStream fos = context.openFileOutput(filepath, Context.MODE_PRIVATE);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(data);
oos.close();
//読込
FileInputStream fis = new FileInputStream(filepath);
ObjectInputStream ois = new ObjectInputStream(fis);
S data = (S)ois.readObject();
ois.close();
ファイルを読み込むときもObjectInputStream.readObjectで開いてキャストするだけで復元できます。 ただし、シリアライズではこんな落とし穴やこんな注意点もありますので、お気をつけて…

2013年6月18日火曜日

SurfaceViewでの画像のタイル描画(繰り返し)

SurfaceViewを扱うとき背景のところを1枚絵で描画しているときはいいですが、小さい画像の繰り返しで済むような場合は、リソースの節約のためにもタイル(繰り返し)描画をしたほうがいいかと思います。
ロジック的には下のような感じ、while分の中で描画したい大きさに達するまで位置を変えて繰り返し描くだけです。

//描画領域Rect
Rect r = new Rect(left, top, left + width, top + height);
//画像幅取得
int imgWidth = background.getWidth();
//画像高さ取得
int imgHeight = background.getHeight();
switch (layout) {
case BACK_FIT : //領域全体
    canvas.drawBitmap(background, imgRect, new Rect(r.left, r.top, r.width(), r.height()), paint);
    break;
case BACK_VREPEAT : //縦の繰り返し
    int sh = 0;
    while (sh < height) {
        canvas.drawBitmap(background, imgRect, new Rect(r.left, r.top + sh, r.width(), imgHeight), paint);
        sh += imgHeight; //画像の高さ分足す
    }
    break;
case BACK_HREPEAT : //横の繰り返し
    int sw = 0;
    while (sw < width) {
        canvas.drawBitmap(background, imgRect, new Rect(r.left + sw, r.top, imgWidth, r.height()), paint);
        sw += imgWidth; //画像の幅分足す
    }
    break;
}

最後の描画で描画領域を考慮していないのではみ出すことがありますが、それで困る場合は先日書いたSurfaceViewで描画範囲を限定するを利用するとよいでしょう。