2013年9月25日水曜日

2012年12月27日木曜日

Circular dependencies cannot exist in RelativeLayout


最近のADTではレイアウトの変更が簡単になったので、RelativeLayoutの属性で苦しんでいる僕にとっては、LinearLayoutでとりあえず組んで、RelativeLayoutに変更っていう手順がすごく楽なのですが、ときどき次のようなエラーが発生してアプリが起動しなくなることがあります。

12-27 15:34:47.104: E/AndroidRuntime(7123): java.lang.IllegalStateException: Circular dependencies cannot exist in RelativeLayout

このエラーはRelativeLayout内でIDを参照しあっている場合に発生します。
なので、そういう箇所をさがして修正してあげると治りますよ。

    <RatingBar
        android:id="@+id/ratingBar1"
        style="?android:attr/ratingBarStyleSmall"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBaseline="@+id/view1"
        android:layout_below="@+id/text4" />

    <View
        android:id="@+id/view1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignTop="@+id/ratingBar1"
        android:layout_toRightOf="@+id/ratingBar1"
        android:layout_weight="1" />

こういうの

2012年12月14日金曜日

Android2.3と4.1のActivityの挙動の違い

Android2.3と4.1でActivityの挙動が少し異なるようなので調べてみました。
ActivityにSurfaceViewが一つあるだけのアプリを作成し、onCreate、onStart、onResume、onPause、onStop、onDestroy、onSaveInstanceState、onRestoreInstanceState、surfaceCreated、surfaceChanged、surfaceDestroyed それとSurfaceViewのコンストラクタにログ出力を入れて呼ばれるタイミングを調査しました。
使用した端末
・HTC EVO (Android 2.3.4)
・Galaxy Nexus (Android 4.1.1)

1.アプリ起動後、戻るボタンで終了
2.3 4.1
onCreate onCreate
SurfaceView Constructor SurfaceView Constructor
onStart onStart
onResume onResume
surfaceCreated surfaceCreated
surfaceChanged surfaceChanged
戻る押下 戻る押下
onPause onPause
surfaceDestroyed surfaceDestroyed
onStop onStop
onDestroy onDestroy


これは2.3と4.1で違いはありません。

2.アプリ起動後、電源ボタンでスリープしてから復帰
2.3 4.1
onCreate onCreate
SurfaceView Constructor SurfaceView Constructor
onStart onStart
onResume onResume
surfaceCreated surfaceCreated
surfaceChanged surfaceChanged
電源ボタンでスリープ 電源ボタンでスリープ
onSaveInstanceState onPause
onPause onSaveInstanceState

onStop
スリープ解除 スリープ解除
onResume onRestart

onStart

onResume

スリープ時に違いが二つ有りました。
・onSaveInstanceStateとonPauseの呼び出し順が逆になっている。
・2.3はポーズ状態に遷移しているが、4.1ではストップ状態に遷移している。
アプリによっては影響がありそうなので、注意が必要です。

3.アプリ起動後、ホームボタンで一時停止後、復帰
2.3 4.1
onCreate onCreate
SurfaceView Constructor SurfaceView Constructor
onStart onStart
onResume onResume
surfaceCreated surfaceCreated
surfaceChanged surfaceChanged
ホームボタン押下 ホームボタン押下
onSaveInstanceState onPause
onPause surfaceDestroyed
surfaceDestroyed onSaveInstanceState
onStop onStop
復帰 復帰
onRestart onRestart
onStart onStart
onResume onResume
surfaceCreated surfaceCreated
surfaceChanged surfaceChanged

onSaveInstanceStateとonPauseの呼び出し順が逆になっているのはスリープ時と同じですが、4.1ではonSaveInstanceStateはさらにSurfaceDestroyedより後に呼ばれています。

4.アプリ起動後、端末を回転
2.3 4.1
onCreate onCreate
SurfaceView Constructor SurfaceView Constructor
onStart onStart
onResume onResume
surfaceCreated surfaceCreated
surfaceChanged surfaceChanged
回転 回転
onSaveInstanceState onPause
onPause onSaveInstanceState
onStop onStop
onDestroy onDestroy
surfaceDestroyed surfaceDestroyed
onCreate onCreate
SurfaceView Constructor SurfaceView Constructor
onStart onStart
onRestoreInstanceState onRestoreInstanceState
onResume onResume
surfaceCreated surfaceCreated
surfaceChanged surfaceChanged

これもonSaveInstanceStateとonPauseの呼び出し順が逆になっています。SurfaceDestroyedがonDestroyより後に呼ばれていますが、動きとしては共通です。


まとめ
onSaveInstanceStateがonPauseの前に呼ばれていたのが、後に呼ばれるようになったようです。ポーズ後に状態を保存するほうが合理的な気はします。ただし、呼び出し順で挙動が異なるようなアプリでは注意が要ります。
また、2.3ではストップ状態ではSurfaceDestroyedはすでに呼ばれている、あるいはすぐ後で呼ばれる(回転時)はずですが、4.1ではストップ状態に遷移しても、SurfaceDestroyed が呼ばれ無いケースがあります(スリープ時)。この辺の動きにも注意が要りそうです。
なお、手元にAndroid4.0の端末がないので試していませんが、4.1と同様の挙動だろうと思われます。

2012年11月27日火曜日

Android OpenGL ES ワンポイントテクニック その1

OpenGLでテクスチャを貼ったポリゴンを表示した場合、デフォルトでは、表も裏も表示されます。回転させた場合など、裏面が表示されているときは裏返しの画像になるわけですね。
裏面を表示させたくない、あるいは裏面だけを表示したい場合、カリングという機能を使います。

  // カリングを有効化、表か裏しか描画されなくなる
  gl.glEnable(GL10.GL_CULL_FACE);

  // 両面描画するよう戻すときは、カリングを無効化します。
  gl.glDisable(GL10.GL_CULL_FACE);


描画しない面を指定するときは、glCullFaceを使います。
  // 表面のみ描画                
  gl.glCullFace(GL10.GL_BACK);

  // 裏面のみ描画
  gl.glCullFace(GL10.GL_FRONT);

glCullFaceのパラメータは「描画しない面」であることに注意してください。

応用例として、くるくる回るトランプを考えます。
テクスチャとして、トランプの表と裏、それぞれの画像を用意しておきましょう。

onSurfaceChangedなどで、カリングを有効化しておきます。

  // カリングを有効化、表か裏しか描画されなくなる
  gl.glEnable(GL10.GL_CULL_FACE);

onDrawFrameでトランプを描画するとき、表と裏それぞれの画像を同じ座標、同じ大きさで描画します。その時に、glCullFaceでどちらの面を表示するか指定します。

  // 表面のみ描画                
  gl.glCullFace(GL10.GL_BACK);
  トランプの表画像を描画する

  // 裏面のみ描画
  gl.glCullFace(GL10.GL_FRONT);
  トランプの裏画像を描画する

これで、トランプをくるくる回転させると、表が見えているときは表の画像、裏が見えているときは裏の画像が表示されるようになります。



2012年11月20日火曜日

MacでAndroidの標準ブラウザをビルドする方法

Androidのソースには、Android標準のブラウザ等のソースも含まれています。

ここでは、MacでAndroidの標準ブラウザをビルドする方法について解説します。

まずは、Android OSのビルドを行う必要があります。

MacでAndroid OSのビルドを行う場合、大文字小文字を区別するパーティションを用意して、そこにAndroidのソースを取得する必要があります。
こちらのサイトなどを参考に、Android OS のビルドを行って下さい。
http://techbooster.org/android/hacks/4920/

ただし、2012/11/20現在のところ、repoコマンドのダウンロードやソースコードのアドレスが変わっているようなので、それぞれ以下のようにして下さい。

・repoのダウンロード
curl https://dl-ssl.google.com/dl/googlesource/git-repo/repo > ~/bin/repo

・repoの初期化(ジンジャーブレッドのソースを取得する場合)
repo init -u https://android.googlesource.com/platform/manifest -b android-2.3.7_r1

これらのアドレスは、また変更になるかもしれません。

OSのビルドが終わったら、ブラウザのビルドを行います。
ブラウザはEclipseのプロジェクトになっていないため、ターミナルからビルドします。


cd packages/apps/Browser/
として、ブラウザのフォルダに移動します。
ブラウザのフォルダで、
mm
を実行すると、ブラウザがビルドされます。





2012年11月14日水曜日

MacにAndroidのCocos2d-xの開発環境を構築する方法、その2

前回、Cocos2d-xの開発環境をMacにインストールし、実行するところまで解説しました。
しかし、C++のソースをテキストエディタで編集し、ターミナルからビルド、Eclipseで実行するという、手間のかかる環境でした。
今回は、C++のソースの編集とビルドもEclipse上で行うための設定を解説します。
前提条件として、EclipseにCDTがインストールされている必要がありますが、最新のADTをインストールするときにNDK Pluginsをインストールしていれば、CDTもインストールされます。NDK Pluginsをインストールされていない方は、ADTの新規インストールを行ってNDK Pluginsをインストールしておいて下さい。


・C/C++ Projectsに変換する。
前回作成した、Cocostestプロジェクトを元に説明します。
まずは、プロジェクトをC/C++ Projectsに変換します。

プロジェクトを右クリックして、「New」→「Others」と選択して「Select a wizard」ダイアログを表示表示します。

「C/C++」ツリーの「Convert to a C/C++ Project(Adds C/C++ Nature)」を選択し「Next」ボタンを押下します。

「Convert to C or C++」のエリアでラジオボタン「C++ Project」を選択します。

「Project type:」のエリアで「Makefile project」を選んで「-- Other Toolchain --」を選択します。
※環境によっては「Android GCC」などという選択肢が現れますが、これを選ぶとえらい目にあうので気をつけましょう。

「Finish」ボタンを押下します。

・Eclipseからビルド出来るよう設定をする。
次にビルダの設定をします。
プロジェクトを右クリックして、プロパティを選択します。

「C/C++ Build」を選択します。
「Use default build command」のチェックを外します。
「Build command」に以下のように入力します。
bash ${workspace_loc:/Cocostest}/build_native.sh NDK_DEBUG=1 V=1
※ Cocostestのところはプロジェクトに合わせて変更して下さい。


「OK」ボタンを押下します。

一度、プロジェクトをビルドしてみましょう。
「please define NDK_ROOT」と表示された場合、環境変数の設定が必要です。
Macの場合、plist で NDK_ROOTにNDKのパスを設定する必要があります。

「~/.MacOSX/environment.plist 」を編集しますが、Xcodeがインストルされていれば、environment.plist をダブルクリックすると、Property List Editor が起動します。
使い方は、こちらのサイトが参考になります。
http://www.ki.nu/software/macosx/property-list-editor.html

NDKのパスはフルパスで入力する必要があります。
environment.plist を変更したら、変更を反映させるにはMacを再起動する必要があります。Macを再起動しましょう。

これで、Eclipseからビルドが出来るようになったはずです。

・EclipseでC++のソースを編集できるようにする

次に、C++ ソースの編集を出来るようにします。

プロジェクトを右クリックして、プロパティを表示します。
「C/C++ General」から「Paths and Symbols」を選択します。

「Source Location」タブを選んで、「Link Folder...」ボタンを押下します。

「Folder name:」に「Classes」と入力します。
「Link to folder in the file system」にチェックを入れて「Browse」ボタンを押下します。
プロジェクトフォルダ直下の「Classes」フォルダを選択して、OKボタンを押下します。

これで、EclipseからC++ のソースを開けるようになります。試しにEclipseからClassesフォルダのHelloWorldScene.cpp をダブルクリックしてソースをエディタで開いてみてください。エラーが沢山表示されると思います。

エラーを解消していきましょう。

まずは、インクルードパスを設定します。

プロジェクトを右クリックして、プロパティを表示します。
「C/C++ General」から「Paths and Symbols」を選択します。

「Includes」タブを選んで、「Languages」から「GNU C++」を選択します。
「Add...」ボタンを押下すると、パスの設定ダイアログが開くので「File System...」から、以下の二つを追加します。

~/dev/cocos2d-2.0-x-2.0.4/cocos2dx/include
~/dev/android-ndk/platforms/android-14/arch-arm/usr/include
※「~/dev」は、インストールされている環境に合わせて変更してください。

まだ、沢山エラーが出るので、エラーを無視するように設定します。
プロジェクトを右クリックして、プロパティを表示します。
「C/C++ General」から「Code Analysis」を選択します。

ラジオボタンの「Use project settings」を選択します。
「Problems」のリストから「Syntax and Semantic Errors」のチェックを外します。

これで、Eclipseからソースの編集とビルドを実行出来るようになりました。
便利ですね。

2012年11月9日金曜日

EclipseのContentAssistが使えなくなったとき( No Default Proposals)

Eclipseを使っていてある日突然コード補完(ContentAssist)が使えなくなった人いませんか?
僕もちょっと嵌ってしばらくContentsAssistなしの生活を強いられて苦しい思いをした口です。


にっくきこの画面、再インストールしたのに!と思う人もいるかもしれません、そして、それをそのへんの人に八つ当たりしちゃうとたまったもんじゃないですね。

こういうときは次の設定を試しててみてください。
Eclipseの設定からJava→Editor→Content Assist→Advanced
を選択し、Java Proposalsにチェックが入っているか確認してください。


多分、チェックが外れてる・・・