スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

Android 作成したAPKファイルで自クラスがNoClassDefFoundError


         ,. -‐'''''""¨¨¨ヽ
         (.___,,,... -ァァフ|          あ…ありのまま 今 起こった事を話すぜ!
          |i i|    }! }} //|
         |l、{   j} /,,ィ//|     『おれは生成したAPKファイルを端末でテストしようとしたら
        i|:!ヾ、_ノ/ u {:}//ヘ      自分のクラスがないってエラーがでる』
        |リ u' }  ,ノ _,!V,ハ |
       /´fト、_{ル{,ィ'eラ , タ人        な… 何を言ってるのか わからねーと思うが
     /'   ヾ|宀| {´,)⌒`/ |<ヽトiゝ        おれも何をされたのかわからなかった…
    ,゙  / )ヽ iLレ  u' | | ヾlトハ〉
     |/_/  ハ !ニ⊇ '/:}  V:::::ヽ        頭がどうにかなりそうだった…
    // 二二二7'T'' /u' __ /:::::::/`ヽ
   /'´r -―一ァ‐゙T´ '"´ /::::/-‐  \    催眠術だとか超スピードだとか
   / //   广¨´  /'   /:::::/´ ̄`ヽ ⌒ヽ    そんなチャチなもんじゃあ 断じてねえ
  ノ ' /  ノ:::::`ー-、___/::::://       ヽ  }
_/`丶 /:::::::::::::::::::::::::: ̄`ー-{:::...       イ  もっと恐ろしいものの片鱗を味わったぜ



ってポルナレル状態になってしまったのだが・・・


作成したアプリをリリースするためにEclipseからAPKファイルをエクスポートし、
端末へ手動インストール、またはDevelopコンソールからのベータ版としてインストールしてテストしようと思ったのだが、まず最初にActivityの実行中にエラーが発生して異常終了する。

エラーは「NoClassDefFoundError

AndroidでNoClassDefFoundErrorをググるとよく出てくるのが
「外部JAR」が取り込まれていないという問題。
これについては、プロジェクトのプロパティから対象のJarにエクスポートでチェックすれば解決できるのだが、私の問題はこれではなかった。

外部Jarではなく自分で作成したクラスがNoClassDefFoundErrorとなっているのだ。

ちなみにプロジェクト構成は
・プロジェクト
 →src
  →hoge.hoge
   →log.class
 →Android4.1

ここでいう共通ログクラスとして作成したlogクラスがNoClassDefFoundErrorになってしまっている。


でさらに困ってしまったのが
1.Eclipseから直接デバッグ実行したときにはエラーが発生しない
2.エクスポートしたAPKファイルをインストールするとエラーが発生する

という本当に不思議な状態になってしまった。

つまりはAPKを作成する際に、必要なクラスがすべて含まれていないみたいなのだ。

ちなみに環境としては
OS Win7
Eclipse4.2
ADT 22
Java 1.6
プロジェクトの対象SDKは4.1

最初はADTがおかしいのかもと思い、再インストール、Eclipse再インストールなどいろいろやったが改善されず。

それに何回もAPKファイルを作成してわかったことなのだが、その都度APKファイルの容量が異なるのだ。
100k程度の差が現れる。
たぶん必要なclassファイルが含まれていないからなのだろう。

これには困った・・・ デバッグ実行では問題なく動作するのだから・・・



■ファイル共有ソフト(DropBox、SkyDrive、GoogleDrive、しゅがーしんく(だっけ?))を利用する場合はご注意を

なぜここに行きついたのかよくわからなかったが、原因はこのファイル共有ソフトだった。

数か月前から複数の端末(家や会社など)でソースファイル(workspace自体)を共有したいと思い、紆余曲折があってSkyDriveで開発関連のソースやアプリケーションなど共有することにした。
使い方としては、ローカルのEclipseからSkyDriveにあるプロジェクトを参照して開発する形となっている。


原因はというと、たぶんAPKに必要なclassファイルをこの共有ソフト側が掴んでしまったことで、Eclipse側(ADT側)でAPKファイルを作成するときに使用できなかったのだと思う。
※エクスポートするタイミングでコンパイルが(たぶん)走るため、classが更新されて、それをファイル共有ソフトが検知してサーバへアップするために掴んでると思われる。たぶん。


そのため、一旦SkyDriveを終了させてからAPKのエクスポートをしたところ、やっと正しくAPKを作成することができた。
※SkyDriveは設定で「複数のファイルを纏めてアップ・・・」の設定があるのだが、これをチェックしている、理由はわからんが何かファイルにやっているのだろうか。SkyDriveを終了させてもAPKが正しく作成されない場合がある。

私のようにソースファイルをSkyDriveで共有する場合には
1.設定「複数のファイルを纏めてアップ・・・」のチェックを外す
2.APKファイルを作成するときには、SkyDriveを終了させる
3.それでもダメな場合はPCの再起動後、APKを作成
スポンサーサイト

AndEngine メモリ節約術 その1

ということでもないのだが、私が開発している中で嵌ってしまったことのメモ。


画像表示にSpriteを利用しているが、メモリ節約のため「ITextureRegion」を使いまわそう、とある。

そのため、ITextureRegionを使いまわしてSprite(AnimatedSprite)を作成していたのだが・・・





作成しているゲームの性質上、エフェクトを多用しているため敵と戦っているときに沢山の斬撃エフェクトをAnimatedSpriteで乱発させていたのだが、数分立ってくると画面全体がもっさり動作になってしまい、挙句の果てにスマホ自体の描画がおかしくなってしまったのだ。

たぶんだが、斬撃エフェクトが千個近く生成されてしまったのが問題みたいだ。

ITextureRegionは使いまわしているのだが、そのつどAnimateSpriteを生成して、アニメーションが終わったらdetachしているのだが・・・
やはり、当たり前だが貼り付けるSpriteは少ないほうがいいみたい。


そこで、以下の対応をした

1.同じSpriteは初めに作っておいて、detachもしくはアルファ値を0にして見えないようにしておく
2.表示のタイミングでattachもしくはアルファ値を1にして表示する。
3.アニメーションがある場合は、アニメーションの設定を行う。
4.アニメーションが終わったらdetach、またはアルファ値を0にして非表示する
5.また表示するときは1から始める


なにを当たり前のことを・・・っていうのは勘弁w

AndEngine初心者にはやることすべてが初めてなんでw

これやってない人にはお勧めですお。

AndEngine OutOfMemoryについて

AndEngineは気を付けてコーディングしないとOutOfMemoryが頻発する。

ついつい私みたいなJavaやC#に慣れている世代だと「メモリの解放」ということ自体が頭からないため困った困った・・・

■Spriteに読み込んだ画像の解放を忘れずに

私が参考にした以下参考書には書いていなかったのだが、、、



基本的にSpriteを作成するには以下の手順で作成する(はず・・・)
1.gameActivity.getResources().getAssets().open(ファイル)によるInputStreamの生成
2.InputStreamからBitmapの生成
3.BitmapのサイズをもとにBitmapTextureAtlasの作成
4.gameActivity.getEngine().getTextureManager().loadTexture()でBitmapTextureAtlasのロード開始
5.Spriteの生成

で、ゲーム内で画面(Scene)の切り替えなどの時に明示的に表示したSpriteを解放している。
Sprite.detachSelf()やnull格納など。

参考書には上記をやって「メモリ解放しよう」と記載されているが、これだけだと実はちゃんとメモリ解放できていない。

■BitmapTextureAtlasの解放

実は「BitmapTextureAtlas」の解放が必要なのだ。


なので、画面の切り替え時などにSpriteなどを解放するタイミングで、同じように「BitmapTextureAtlas」も解放してあげる。


bitmapTextureAtlas.unload();
bitmapTextureAtlas.clearTextureAtlasSources();
bitmapTextureAtlas= null;


上記三つやると問題ない(と思う・・・)

私はSpriteなどを生成するときに作成する「BitmapTextureAtlas」をどっかにstaticでリスト管理して、画面遷移時にまとめて解放処理を行っている。
※もちろんSprite表示中に「BitmapTextureAtlas」を解放しちゃうと画像が表示されないからね!!


これはAnimatedSpriteでも同じ

AndEngine SDカード上、Web上の画像でSpriteを作成する

AndEngineを利用した初ゲームアプリが完成しました。


ゲーム「バグズ・ウォーズ」
icon2.png


今までScriptの「enchant.js」を利用して作っていたのだが、FPSなどの問題で開発途中でAndEngineで作り直すことにした。
ネット上ではAndroidでのゲームアプリエンジンの本命だ、と言われているが、私もそうだと思う。

ちなみに参考にしたのがこの参考書。

他のAndEngineの参考書は見たことないのだが、これ1冊こなせばAndEngineの開発は一通りこなせると思う。


■assetsフォルダ以外からSprite、AnimatedSpriteを作成するには??



画像を表示するにはSpriteを利用するのだが、
この参考書だからなのかわからないが、基本的にもととなる画像はプロジェクトのassetsフォルダにある画像を利用しているのだ。

画像を扱うためのクラス内で、画像を読み込むためのパスルート(?)がデフォルトassetsフォルダが固定されているため、画像を読み込むときに指定するファイルパスはassetsフォルダからの相対パスを指定している。

しかし、今回このassetsフォルダ以外から画像を読み込む必要が出てきたからさーたいへん。

■拡張ファイルの利用


今回作成したバグズ・ウォーズは大量の画像ファイルを利用するため、APKが50MBを超えてしまった。
そのため、画像ファイルを拡張ファイルとして提供することにしたのだが、拡張ファイルを利用してしまったため、画像ファイルがassetsフォルダ以外に存在する状況となってしまった。

考えたのだが、このSDカード内に作成された画像ファイルを、アプリ起動時にassetsフォルダにロードすればいけるんじゃね??と思ったのだが、そもそもassetsフォルダはAPK内部に存在しており、assetsフォルダに後で追加するということ自体が不可能だということが分かった。



ということで、以下がSDカード内の画像をSpriteに読み込む方法。

■ソース

String fileName = "ファイルパス";
TextureRegion imageFromServer = null;
ITexture mTexture = new BitmapTexture(
gameActivity.getEngine().getTextureManager(),
new IInputStreamOpener() {
@Override
public InputStream open() throws IOException {
InputStream input = new FileInputStream(fileName2);
BufferedInputStream in = new BufferedInputStream(input);
return in;
}
});
mTexture.load();
textureList.add(mTexture);
imageFromServer = TextureRegionFactory.extractFromTexture(mTexture);

Sprite sp = new Sprite(0, 0, imageFromServer, gameActivity.getEngine().getVertexBufferObjectManager());


■ちなみにAnimatedSpriteは

String fileName2 = ""ファイルパス;
int column = 3;
int row = 3;
TiledTextureRegion imageFromServer=null;
ITexture mTexture = new BitmapTexture(
gameActivity.getEngine().getTextureManager(),
new IInputStreamOpener() {
@Override
public InputStream open() throws IOException {
InputStream input = new FileInputStream(fileName2);
BufferedInputStream in = new BufferedInputStream(input);
return in;
}
});
mTexture.load();
textureList.add(mTexture);
imageFromServer = TextureRegionFactory.extractTiledFromTexture(mTexture,column, row);
// AnimatedSpriteを生成
AnimatedSprite sp = new AnimatedSprite(0, 0, imageFromServer,gameActivity.getVertexBufferObjectManager());



■ちなみにWeb上の画像を読み込むには
InputStreamを以下に変更すればよい

//画像URL
URL url = new URL("http://aaaaaaaaaaaaa");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.connect();
InputStream input = connection.getInputStream();


これでassetsフォルダ以外の画像データを扱うことができる。
おすすめアプリ
カテゴリ
最新記事
リンク
アクセスカウンター
アクセス解析
imobile
i-mobile
i-mobile
i-mobile
i-mobile
i-mobile
検索フォーム
RSSリンクの表示
リンク
ブロとも申請フォーム

この人とブロともになる

QRコード
QR
Amazon
Androidお勧め参考書
EC studio
商品
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。