【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マーケットにリリースしました!!、(*^0^*)ノ

でも、ダウンロードした方のスマフォでちゃんと動くか不安です。:;
ここのブログを見てダウンロードした人は、ぜひぜひ感想なり、バグ報告なりください^^

【 ねこニャンの百マス計算をダウンロード 】
https://market.android.com/details?id=net.darkdrive.android.hmas&feature=search_result

20110610_hmas1

↓ケータイからダウンロードしたい方はコチラ

20110610_hmas2

百マス計算とは、縦10・横10のマスの左と上の数字をランダムに並べそれぞれ交差するところに
指定された計算方法で答えを記入する計算トレーニングです。本アプリではたし算(20問)、ひき算(20問)、かけ算(15問)の3種類の計算方法と問題を選択でき、
遊ぶことができます。各種問題のタイムの記録、11問目~15問目は時間制限のある問題を用意しております。
百マス計算を効果的に遊ぶ方法としては定期的に簡単な問題を解くことが脳の活性化によいと
されています。早くやることに囚われることなく脳トレ用のアプリとしてご活用いただけたら幸いです。

★ゲーム仕様
たし算 全20問 (11問~15問目は時間制限あり問題)
ひき算 全20問 (11問~15問目は時間制限あり問題)
かけ算 全15問(11問~15問目は時間制限あり問題)

次の問題に進むときはパネルをページをめくるようにタッチ(もしくは下の「→」キーを押す)と次の問題に移動します。
また近いものがみづらい方のためにも拡大、縮小を用意しています。(問題参照時に調整することが可能です。)
※時間制限のある問題は私、制作者側の意向としましては平均的にこれくらいの速さで解けるのが一般的ではないか、という
時間を制限に設けたいと考えています(現時点では大目の時間を設定しています)が、こればかりはダウンロードしてくださった皆様が実際に解いた時間の平均を算出し、アプリに修正をかけたいと考えております。

もしお手数でありませんでしたら、問題と解いた時間を教えていただけたら幸いです。
不具合などありましたら、すぐに対応できるようにいたしますので随時ご報告ください。

2011.6.10
神森 真昼

追記(2011.6.14)
おかげさまで「ねこニャンの百マス計算」はリリース2日目で100ダウンロード突破しました(・▽*)ノ
初めて作ったアプリをたくさんの方にダウンロードしていただき光栄です。
次回作のアプリを現在作成中ですので、今後もよろしくお願い致します。

追記(2011.7.9)
1000ダウンロード突破しました、(^▽^)ノ
ダウンロードしてくださった皆様に心より御礼申し上げます。

【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
神森 真昼