ラベル Android の投稿を表示しています。 すべての投稿を表示
ラベル Android の投稿を表示しています。 すべての投稿を表示

2014年8月10日日曜日

Androidのスマホやタブレットが調子悪くなったら試してみよう

Androidの端末がものすごく重かったり、他の人のは電波つかんでるのに自分のだけアンテナ立たない・・・
そんな症状でお困りでしたら、以下を試されると幸せになれるかもしれませんよ?



(1) 携帯のアンテナが立たなかったり、立ったてもすぐに消えたり
原因:SIMカードの端子が汚れている

対処:
スマホの電源を落としてSIMカードを外します。
SIMカードの金属端子部分を綿棒等でゴシゴシ掃除します。
はぁ~っと息を吹きかけて、その湿り気を乾拭き。でも十分ですが、
表面が薄く酸化してたり、ヤニとかで覆われている場合には、アルカリ電解水を綿棒に少しだけ付けて擦ると効果があります。
ティッシュ等で良く水分を拭きとってからスマホに装着し、電源を入れて確認してみてください。

それでもダメな場合、SIMカードが壊れているか、スマホが壊れているかのどちらかです。
使ってない予備スマホがあって、同じ大きさのSIMカードが刺されば、自宅でも確認できます。
面倒ならショプに行きましょう。



(2) Android端末で動作が異様に重い
原因:スマホのメモリ(RAM)の空きが少なすぎる

足りないのはアプリを入れておくフラッシュメモリではなく、アプリを動かす時に使う一時メモリ(RAM)です。これは作業机の様なもので、机の上にモノがあふれかえっていて、まともに仕事できない状態と同じになってます。

対処:
Advanced Mobile Care(AMC)等のアプリで、余計なアプリを一時的に止めてみます。
解決したなら、不要なアプリをアンインストールしてみます。
この時、一度再起動してからでないと効果が出ない場合が多いようです。
AMCはアンチウィルスも付いていて便利です。同種のアプリを色々試しましたが、使いやすく安定しているのでオススメです。



(3) 操作できないレベルで動きが重い
原因:SDカードのデータが壊れている

スマホの各アプリが自分の保存データを読み書きしようとするのですが、出来ないのが分かるまでにずーと待ちぼうけしてしまいます。この為、スマホの中で大渋滞が発生し、ほとんど動かせなくなってしまいます。
スマホのアプリは、SDカードが刺さってるとアプリのセーブデータをSDに書き込むものが多く、実はそのSDカードの「フォーマットの一部が壊れてしまう」事が頻繁に起こります。

保存したファイルが壊れるのではなく「フォーマット」から壊れてしまうと、データの読み書きができなくなるだけでは無く、壊れているのかどうかが分かるまで、かなりの時間がかかってしまいます。

対処:
SDカードから必要なファイル、例えば撮影した写真などをバックアップし、SDカードをPCで初期化します。この時「クイックフォーマット」のチェックを外す必要があります。
フォーマットの形式は「FAT32」で問題ないはずです。
もしスマホでそのまま使えなかった場合、改めてスマホの設定からSDカードを初期化して下さい。



対策は以上です。

そもそも使っているアプリの組み合わせでメモリが足りてない場合には、買い替えを検討される時期でしょう。
次はRAMの搭載量も気にして選ぶと良いでしょう。最近のモデルでしたらRAM2G以上を探すと、かなり長持ちすると思いますよ。



2014年6月9日月曜日

今更ですが、OpenGL ESは1.1と2.0、どちらを選ぶべき?

スマホ・タブレット向けゲームアプリを本気で制作しようとすると、OpenGL ESでの描画は避けて通れませんね。
で、実際にサンプルでも動かそうとする場合に、1.1と2.0では処理の仕方/書き方が少々違っている。という所までは簡単にに調べが付きます。
では、どちらで開発すれば良いのでしょか?

結論から言えば、現状では未だOpenGL ES 1.1 を使うしかないと考えます。

ではどう違うのでしょうか?


●OpenGL ES 1.1
・GPUの負荷が軽いので、ごく一部の画面の更新速度が元から30fpsの端末を除けば、60fps以上を出せる。
Android2.2~2.3の頃の端末でも、比較的動作が安定している。
・シェーダーが使えないのは致し方ないが、レンダリング先をスクリーン以外に行うなどの便利機能が無くて痛い。
・仕様が枯れているので、ネットで情報を集めやすい。

●OpenGL ES 2.0
・シェーダを駆使すれば、PCゲー並みの描画が実現可能。でもGPUの負荷が重い。
・たとえアプリを軽く作っても、OpenGL側で30fpsが頭打ちになってしまっている。
・Android2.2~2.3の頃の端末では不安定な挙動が散見されているらしい。
(↑これは聞いた話なので未確認です)
・シェーダプログラミング自体が開発の負荷になるし、そもそも書籍でもネットでも良い情報が得られにくい。


GLES2.0はシェーダに触れなくても30fps以下しか出ません。これは動きのあるゲームでは致命的です。
ゲームの歴史的に30fps以下のハードでは、ソフトウェアが良い評価を得る事が非常に難しくなります。
まぁゲームの操作性は気にしない。フォトリアルまっしぐらな方はGLES2.0以降でも良いですし、今後ハード(GPU)の性能自体が数倍に跳ね上がれば、GLES1.1はレガシーになり消えていくのでしょう。

2014年の現在、ファミコン程度の操作性を実現する為にはOpenGL ES1.1しか選択の余地がない。という事でした。



2014/07/16 更新 OpenGL ES 2.0以降だと30fpsが頭打ちと書きましたが、最新のGPUではそうでもない様です。 僕の情報が半年~一年遅れだったかもしれません。 ただし多くのユーザーの機種には、未だ重たいのが現状のようです。 GPUのパワーが上がっているのは確かですが、画面解像度もFullHDが当たり前になりつつあるので、その分相殺されています。 もう1~2年待たないと60fpsは辛そうだな、と僕は予想しています。

2014年5月16日金曜日

Androidのデバッグ用に、クラス名・メソッド名・行番号を表示する

ゲーム開発ですと、統合環境のデバッガでのんびり見てられない事が多いので、自前でデバグ出力を何とかする必要があります。

LogCatに出力するLogクラスが有りますが、以下な感じの便利メソッドを何処かのクラスに置いておくと便利です。

public static void Debug(String _msg) {
Throwable throwable = new Throwable();
StackTraceElement stack = throwable.getStackTrace()[1];
int line = stack.getLineNumber();
String func = stack.getMethodName();
String cls = stack.getClassName();
Log.i("ProjectName",cls+":"+func+"/"+line+" "+_msg);
}

これを任意の場所で呼び出せば、呼び出し元のクラス名・メソッド名・行番号を表示できます。
VMの実行環境を拾ってくるだけですね。
もちろんLog.i()で出力しないで利用しても問題無いです。




2013年10月28日月曜日

Fatal signal 11 (SIGSEGV) ・・・ なんだよこれ!

何の音沙汰もなくアプリが落ちる。
あまつさえ端末が再起動し始める。

こんな場合、OpenGLのBuffer問題を考慮してみるのが有効かもしれません。
WebViewを使っている時も原因は同じようですが、こちらはクラスライブラリ内部の話なので解決策はよく分かりませんが。

先ず発生条件ですが、OSでは

・GB以前は無かった。ICS以降。ICSでも初めは問題なかった。

で、端末では

・シングルコアでは見た事が無い。どうもデュアルコア以降らしい。
・ainol Novo7Fire(CM10.1)だと起動後暫くすると発生。
・SAMSUNG GalaxyTab7.7Plusだと起動直後にフリーズ。

アプリでは

・別のスレッドでOpenGLを叩いている。
・例外では何も拾えない。

となります。何が推測できるかといいますと、

どうもGPUが参照中にアクセス保護しているメモリ領域に対して、アプリ側がコンフリクトを起こしている。

という事です。

OpenGLにデータを渡すためにnioのBufferクラスを使いますが、内部で持っているネイティブのメモリアクセスに対して何もしてなさそうです。
OpenGLに渡したBuuferへのアクセスを、OpenGLを叩いているスレッドだけに絞ると、このエラーはピタッと収まりました。

こんな事がありましたので、ご参考になれば。



2014/07/16 追記

少し具体的な説明です。
OpenGLは初期化したスレッドからのみ呼び出しが可能という仕様は知られていますが、
Javaで呼ぶ場合にデータを渡すために使ったBufferクラスのインスタンスへの書き込みも該当します。
OpenGLがBufferのメモリを覗いてせっせと描画している時に、別スレッドからBufferのメモリにアクセスするとコケるという具合です。

解決策としては、メインのスレッドではBufferに直接書き込まず、更新用の情報を別に用意します。
OpenGLを叩くスレッドで、描画する前に更新内容をBufferに適用すれば問題解決です。
面倒くさいんですが、マルチコアCPUの恩恵を受けるためには致し方ありません。








SAMSUNGてめ~w (初代ギャラタブとかのテクスチャが表示されない場合)

今更で需要は少ないかもしれませんが、古い機種も対応される方向けに・・・

SAMSUNGのAndroid2.2系端末、初代ギャラタブとかですね。この頃の機種はOpenGLのドライバに悲しいバグが色々あるのですが、検索で見つからず難儀した事を思い出したので軽く。

テクスチャ絡みで、テクスチャに割り当てるIDを払いだしてもらえるメソッドがあります。

結論:
そのメソッドを使ってはいけません。
(なんてメソッドだったか調べるの面倒くさいので、各自でよろしくです)

何故か:
負の値が払い出される事がある。その値をそのままテクスチャのバインドに使うと、そのIDに割り当てたテクスチャは呼び出せない。

gl.glBindTexture(GL11.GL_TEXTURE_2D, id);
GLUtils.texImage2D(GL11.GL_TEXTURE_2D, 0, bmp, 0);

これで id<0 だと、描画時にもう一回バインドしても何も描画されません。
ま、gl.glBindTexture()が負の値を受け付けないというか、0以下はバインド解除なんで当然なんですけれど。
ちなみに払い出しID値の法則性は不明。他のメーカーの端末とは異なり意味不明なバラバラな値。なんか擬似乱数っぽい感じでした。

解決策:
自分で適当なカウンタを用意して、それを勝手にIDとして使います。
IDはかぶらなければ、特に問題なかったです。OpenGLって、結構てきとうな作りですね。


assetに置いたファイルがMediaPlayerで再生できない → 解決


タッチのコントロールクラスが良い感じに片付いたので、そろそろほっぽっといたサウンド関連に着手しました。
で、MediaPlayerでassetに置いた.oggファイルを再生しようと思ったら、思いっきり躓きました。

普通にMediaPlayerを継承したクラス内で

AssetFileDescriptor afd = asset.openFd(filename);
try {
    setDataSource(afd.getFileDescriptor());
    prepare();
    start();
} catch (Exception e) {
    //
}

こんな感じで書けば音が鳴るんですが・・・というか鳴ってたんですが、しばらくするとprepare()で

java.io.IOException: Prepare failed.: status=0x1

となり、失敗するようになりました。
その前に数回は再生されていて、テスト端末を疑って再起動なども行いましたが変わらず。意味が分かりません。
このエラーの文言で検索しても不明でしたが、何とかなりました。
結論としてはsetDataSource()の所を

setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());

こうしないとダメでした。なんでだ?
オフセットと長さを指定しないと例外って、AssetManager絡みの実装不具合っぽいですね。

とりあえず音関係クラスの実装が続きます・・・


--------その後


・・・一応、使える所まで完成しました。

ゲームに使う時のMediaPlayerとSoundPoolの切り分けが、使い勝手に直結するので難しかったです。
その内落ち着いたら、実装したものの解説でもしようかと思ってます。