カテゴリー別アーカイブ: アプリ開発

【Androidアプリ作成】logcatを使って効率良くデバッグをしよう

こんにちは、NECOです。

Android開発を行う際、
変数の中身を確認したいことが多々あります。

昨今のIDEならば、ステップ実行を行えば
比較的簡単に確認できたりしますが、
やはりデバッグの基本はログ出力かと思います。

Javaの場合、以下のようなコードで
確認するのが一般的かと思われます。

System.out.println("Cat#eat food=" + food);

ですが、Androidでは標準出力や標準エラーといったものが
存在しません。

じゃあどうすればいいんだー!ってことで登場するのが、
「logcat」です。

logcatとは、Androidにはログを集めて表示する機能で、
adbのシェルから表示したりフィルタリングするといったことが行えます。

ログを出力する場合は、以下のようになります。

Log.d("CatLife", "Cat#eat food=" + food);

またログを見る場合は、Eclipseプラグインならば
DDMSパースペクティブのLogCatビューから確認できます。
以下のように出力されます。

06-18 19:00:19.128 D 2664 CatLife Cat#eat food=カルボナーラ

コマンドラインでlogcatでログ表示する場合は
事前にadbサーバーを起動しておきます。Eclipseを使った場合は裏で自動で起動してます。

> adb start-server

adbが起動できたら、次はクライアントのシェルを起動します

> adb shell

adbのシェル上からlogcatを起動します。

$ logcat

以上で行えます。
一連の流れをまとめて実行する場合は、以下のコマンドで行えます。

> adb -s [デバイス識別子] logcat

デバイス識別子は、以下のコマンドで確認できます。

> adb devices

ログを出力して効率よくデバッグを進めましょう。

[参考] logcat | Android Developers

http://developer.android.com/intl/ja/guide/developing/tools/logcat.html

2011.6.19
NECO

【Androidアプリ作成】描画が遅い時はSurfaceViewを使って高速化

ゲームを作っていると、どうしても描画処理が重くなる傾向があります。

そんなときは、ViewをSurfaceViewに呼びかえることで、
描画高速化を期待できます。

以下のようにコードを追加するだけで導入できるので、
お試しください。

■今までのView
public class MyView extends View
{

public MyView(Context context, AttributeSet attrs)

{

this(context, attrs);

}

@Override

public void onDraw(Canvas canvas)

{

super.onDraw(canvas);

~~描画処理~~

}
}

■SurfaceViewに呼び代えたもの
public class MySurfaceView extends SurfaceView
{

public MyView(Context context, AttributeSet attrs)

{

this(context, attrs);

getHolder().addCallback(new SurfaceHolder.Callback() {

public void surfaceDestroyed(SurfaceHolder surfaceholder) {

// nop

}

public void surfaceCreated(SurfaceHolder surfaceholder) {

doDraw(surfaceholder);

}

public void surfaceChanged(SurfaceHolder surfaceholder, int i, int j, int k) {

doDraw(surfaceholder);

}

});

}

private void doDraw(SurfaceHolder holder)

{

Canvas canvas = holder.lockCanvas();

if (canvas == null){ return; }

try

{

onDraw(canvas);

}

finally

{

if ( canvas != null )

{

holder.unlockCanvasAndPost(canvas);

canvas = null;

}

}

}

@Override

public void onDraw(Canvas canvas)

{

super.onDraw(canvas);

~~描画処理~~

}
}

オレンジの部分が、追加した処理です。

2011.6.18
NECO

【Androidアプリ作成】ボタンをもっと角丸にするには?

規定値でもそもそも角丸なのですが、もっと角丸にしたいもしくは角丸をなくしたい場合は
XMLで自分で定義して決めることができます。

このcornersを定義することで角丸を自分でカスタマイズできます。

<corners

android:bottomRightRadius="10dp"

android:bottomLeftRadius="10dp"

android:topLeftRadius="10dp"

android:topRightRadius="10dp"

/>

このcornersをどこに設定して、どうやって使えばいいかは
こちらの記事を参照してください。
こちらにも<corners>が設定されたタグがありますので、そのまま設定を変更して活用できます。
>> ボタンのカスタマイズ

2011.6.16
神森 真昼

【Androidアプリ分析】デベロッパーになると詳細なインストール状況がわかる!

「ねこニャンの百マス計算」リリースして、
晴れてマーケットデビューを果たしたデベロッパーになったわけですが、
デベロッパーになるとアプリごとの詳細な統計情報を参照することができます。

百マス計算は現在100人ぐらいの方がインストールして遊んでいただいているのですが、
その100人がどのプラットフォームで、どの端末で、どの国で、どの言語でプレイされているのかが分かります。

百マス計算はやはり、百マス計算という日本発祥で一番知名度が高いことから
日本人のユーザーが9割で、1割が海外ユーザーとなっています。
海外ユーザーが多い場合は英語もしっかりした文にした方がよいですね!
(私は翻訳ツール使っていますが、もっと上手くかけたらといつも思います:;)

その中でも私が一番気にしているのは端末です。
実機動作環境ではGALAXY Sを使用しているのですが、一番インストールで多い端末が
TOSHIBAのREGZA Phoneです。(ちなみにGALAXY Sは2位でした。)

もしこれがタブレットタイプで表示された場合、
解像度が高い画像を用意したりそれ向けのテストを強化する必要があるかなと考えていたわけですが、
ターゲットユーザーの端末がある程度は予想通りなのでよかったです。
(もちろん、タブレットもシミュレータで動作確認しているので問題ないと思います。)

さらに端末は同じ種類でも、型番別に表示されます。
例えばGALAXY Sなら Samsung Galaxy S
(SC-02B)とSamsung Galaxy S (GT-I9000)が
あるわけですが、前者はdocomoから発売されている端末で後者は海外から発売されている端末です。
日本で後者を使っている方はSIMフリーで購入されていることが多いと思います。

もっと分析して、ゲームを作成することでより多くの方に遊んでいただける
アプリを提供していけたら本望でございます('▽*)ノ
まずは2作目を作ります^^>

2作目もねこが登場するのですが、お勉強ゲームではなく反射ゲームです。
もっと多くの方が簡単に楽しくプレイすることができると思います。
現在鋭意作成中ですが、7月末リリース予定です♪

2011.6.14
神森 真昼

【Androidアプリ作成】InflateExceptionが出た場合の対処法

InflateExceptionが出た場合、
マルチスレッド下でLayoutInflater.inflateを行っていないか確認するといい。

独自クラスを含んだレイアウトをLayoutInflater.inflateで生成する場合、
GUIスレッド以外のスレッドでは動作しない模様。
呼び出すと、以下のような例外が出る。
android.view.InflateException: Binary XML file line #(行番号): Error inflating class <unknown>

ダメな例だが、以前は描画スレッドから以下のような処理をしていた。
呼び出しはGUIスレッド(onCreateやonDrawなど)から行う。

{

final int INTERVAL = 1000/20;

Timer timer = new Timer();

timer.schedule(

new TimerTask() {

@Override

public void run() {

// レイアウト生成

View vw = getLayoutInflater().inflate(R.layout.hogehoge, null);

setContentView(vw);

}

}, 0, INTERVAL

);

}

以下のように書き換えることで、
想定通りの処理が行われるようになった。

{

final int INTERVAL = 1000/20;

final int INFLATE = 1;

// 独自イベント定義

Handler timerHandler = new Handler() {

@Override

public void handleMessage(Message msg){

if ( msg.what == INFLATE )

{

// レイアウト生成

View vw = getLayoutInflater().inflate(R.layout.hogehoge, null);

setContentView(vw);

// 次回のメッセージを作る

long nextTime = Math.max(

msg.getWhen() + INTERVAL

, SystemClock.uptimeMillis());

msg = obtainMessage(INFLATE);

sendMessageAtTime(msg, nextTime);

return;

}

super.handleMessage(msg);

}

};

// 初回のメッセージを送る

Message msg = timerHandler.obtainMessage(INFLATE);

timerHandler.sendMessage(msg);

}

androidはシングルスレッドでGUI処理を行うため、
上記のようにHanderを介して処理する必要がある。
今回のように、レイアウトxmlの構文に問題が無く、上記のような例外が出る場合は
GUI処理に問題が無いか見直してみたほうがいいと思った。

2011.6.13

NECO

【Androidアプリ作成】imageViewクラスで画面背景を設定する

imageViewは画像を表示するために使用するクラスです。
今回はimageViewクラスを使用した画面背景設定方法について記載します。

<ImageView

android:layout_width="fill_parent"

android:layout_height="fill_parent"

android:src="@drawable/game_background" />

※ @drawableの画像は各自で定義してくださいね。
@drawableの定義が分からない方はこちらを参照してください。
>> @drawableでデザイン管理!

このコードを<FrameLayout>定義後、一番に指定します。
FrameLayoutのwidthとheightにはfill_parentを指定してください。

これで実行すればすぐに画面に背景を適用させることができます!

ただ、Androidは小さいやつから大きいタブレットタイプのものまでいろいろありますから、
解像度に応じて画像を用意しておく必要があります。
用意していない場合は小さい画像を引き伸ばして表示されてしまいますので、あしからず。

2011.6.12
神森 真昼

【Androidアプリ作成】広告表示にはViewGroup#addViewを使え

ゲームで広告を表示したいけど、広告のために複雑なプログラムを書くのはちょっとめんどい。

そんなときは、xmlで広告とゲームを同時に表示するレイアウトを作っておいて、
広告用のViewを常時表示しつつ、ゲーム用のViewを必要に応じて入れ替えると
ゲーム部分のプログラムと広告用のプログラムを分離できるので、保守性が高まります。
使うのは以下の2つです。
・LayoutInflater#inflate

// レイアウトリソースIDを指定してViewを生成する
・ViewGroup#addView

// ViewGroupにViewをaddする

■レイアウト(app.xml)
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout

xmlns:android="http://schemas.android.com/apk/res/android"

android:id="@+id/vgApp"

android:layout_width="fill_parent"

android:layout_height="fill_parent"
>

<!–
ゲーム –>

<View

android:layout_width="wrap_content"

android:layout_height="wrap_content" />

<!– 広告 –>

<広告会社提供のView

android:id="@+id/vwAd"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:scrollbars="none"

android:layout_gravity="bottom"

android:layout_marginBottom="0px" />
</FrameLayout>

■Activity
以下のようなメソッドを追加
void setGameView(int layoutResID)
{

// ビューを変更する

View vw = getLayoutInflater().inflate(layoutResID, null);

ViewGroup vgApp = (ViewGroup)findViewById(R.id.vgApp);

vgApp.removeViewAt(0); // 前回のビューを潰して

vgApp.addView(vw,0); // 新しいビューを設定
}

■入れ替えるView(title.xml)
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout

xmlns:android="http://schemas.android.com/apk/res/android"

android:layout_width="fill_parent"

android:layout_height="fill_parent" >

<ImageView

android:layout_width="fill_parent"

android:layout_height="fill_parent"

android:src="@drawable/title_bg"
/>
</FrameLayout>

・・・ここまで来れば、あとは必要なタイミングでsetGameView(R.layout.title)とか呼ぶだけ!楽チン。
Activityのとこに書いてある「vgApp.addView(vw,0);」がミソです。

2011.6.11

NECO

【Androidアプリ作成】@colorで色管理!

@stringと同じ形式で色コードを管理できちゃいます。
今日はその方法を書きます。

まずはvaluesフォルダの中にcolors.xmlというファイルを作成します。
(colorではなくcolorsなのでお間違いのないよう・・・色のデータベース、集合なので複数形になっているとかで覚えましょう。)

【 values-jaフォルダにも同じファイルを入れなくてもいいの? 】
入れる必要はありません。
どんな言語でもvaluesフォルダ内のデータは読み込まれます。
(もちろん、日本語と英語で色を変えたいのであればそれぞれの定義ファイルが必要ですが、
そうでなければ必要ありません。)

【 色管理をするメリット】
string.xmlと同じようにそのファイルを開けばアプリ全体の色修正をかけられるので、
色の差し替えが大幅に楽になります。

colors.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>

<color name="red">#ff0000</color>

<color name="green">#00ff00</color>

<color name="blue">#0000ff</color>
</resources>

【 colors.xmlで定義された色の読み込み 】

試しに赤色が定義されたリソース(red)を呼び出します。

<Button

android:id="@+id/btn01"

android:textColor="@color/red">
</Button>

これは例なのでredとかgreenとかいう名前をつけましたが、
本来ならアプリとかで使用する、タイトルは赤でボタンは緑のように使っていきましょう。
では使ってない人は早速色をリソース化を進めましょう。

2011.6.9
神森 真昼

【Androidアプリ作成】@drawableでデザイン管理!

@stringに引き続き、@drawableについて書きます。
@stringについてはこちらをご参照ください >> @stringで定数管理!

考えは全く@stringと一緒です。
res/drawableフォルダに保存した画像やレイアウトテンプレートを参照できます。
ちなみにdrawableにも日本語と英語を区別するための

drawable-ja (日本語用の素材はここに保存)
drawable

(英語用の素材はここに保存)

【 @stringとはここ違う 】
@stringの場合はstring.xmlがあってそこに書いた定数が呼び出して使えるが、
drawableには画像や使いまわしたいレイアウトのXMLを保存できること!!

【 drawableに保存した画像データを呼び出すには? 】

<Button

android:background="@drawable/画像ファイル名"

android:layout_marginLeft="5dip"

android:layout_marginRight="5dip">
</Button>

※画像ファイル名には拡張子をつけません。
Androidではファイル名をIDとして管理していますので、拡張子は不要です。

【 drawableに保存したレイアウトデータ(XML)を呼び出すには? 】

<Button

android:background="@drawable/レイアウトデータ(XML)名"

android:layout_marginLeft="5dip"

android:layout_marginRight="5dip">
</Button>

※こちらも同じくファイル名に拡張子は不要です。

【 drawableに保存したレイアウトデータはどうやって作ればいいの? 】

下記の記事をご参照ください。
http://blogs.yahoo.co.jp/hiro5_188/20029655.html
ボタンの配色グラデーションのデザインを使いまわすために作成した
レイアウトデータ(XML)です。

素材屋あんどろい堂でもデザインソースを配布していますので、
ぜひサンプルに使ってみてください。

2011.6.8
神森 真昼

【Androidアプリ作成】@stringで定数管理!

前にも「英語と日本語を使い分けるには?」という記事でも多少書いたのですが。
その前にまずは@stringという基本中の基本から掘り下げてみます。

@string ・・・stringファイルから定数を参照しますよってこと
(@drawableもようするに同じことなのです。)


string.xmlを設定するには 】

プログラムで使いたい文章や用語などはあらかじめstring.xmlに設定します。

設定したらここに保存

>>
res/values-ja/string.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>

<string name="blog_name">神森真昼の小説と波の世界</string>

<string name="contents01">Android</string>

<string name="contents02">日記</string>

<string name="contents03">ドロイド君</string>
</resources>

※英語でも対応する場合はstring.xmlの英語バージョンをvaluesフォルダに保存します。


string.xmlに設定した定数を呼び出すには? 】

<Button

android:id="@+id/blog1"

android:text=@string/blog_name">
</Button>

こうやって書くとボタンの表示がさっき設定した
「神森真昼の小説と波の世界」になります。

定数を@stringを使って管理しないと、あとで変更したい場合に
すべてのファイルに修正をかけなければなりません。
とりあえずtextに直接書いてあとで管理・・・などすると怠りがちになりやすいです。
(つまり、私のことなんですが・・・orz

ちゃんと管理しやすいベースを作ってから、楽しくアプリ開発をしていきましょう♪

2011.6.7
神森 真昼