2011年6月18日土曜日

未解決 AdMobをIMEの下に隠したら消えた?

AdMobをIMEの下に隠したら消えた?

超絶的に適当なレイアウトだと消えるようです。
正直どうでもいいんですけど気になって気になって…

また消えること自体も別にいいんです。

消えた事自体を取得できなくて困ってます。

とりあえずこんなレイアウトとソース

main.xml

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

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:ads="http://schemas.android.com/apk/lib/com.google.ads"
 android:layout_width="fill_parent" android:layout_height="fill_parent"
 android:id="@+id/adLayout"
 android:orientation="vertical">

 <EditText android:id="@+id/editText1" android:text="test"
  android:layout_width="fill_parent" android:layout_height="wrap_content">
  </EditText>

 <Button android:text="Button" android:id="@+id/button1"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"></Button>

</LinearLayout>

ソース
private WrapAdView  mAdView  = null;
private AdRequest  mAdRequest = null;

private LinearLayout mLayout  = null;
private Button   mButton  = null;

public void onCreate( Bundle savedInstanceState) {

 super.onCreate( savedInstanceState);
 setContentView( R.layout.main);

 mLayout = (LinearLayout) findViewById( R.id.adLayout);

 initAdmobMakeView();

 mButton = (Button) findViewById( R.id.button1);

 mButton.setOnClickListener( new OnClickListener() {

  public void onClick( View v) {

   // TODO 自動生成されたメソッド・スタブ
   initAdmobMakeView();
  }
 });
}


private void initAdmobMakeView() {

 if( mAdView == null){
  mAdView = new WrapAdView( this, AdSize.BANNER, "Publisher ID");
  mAdView.setAdListener( this);
  mLayout.addView( mAdView);
 }

 if( mAdRequest == null){
  mAdRequest = new AdRequest();
 }

 mAdRequest.addTestDevice( "hoge");
 mAdRequest.addTestDevice( AdRequest.TEST_EMULATOR);

 if( mAdRequest.isTestDevice( this)){
  Log.d( AdRequest.LOGTAG, "test");
  mAdView.loadAd( mAdRequest);
 }else{
  Log.d( AdRequest.LOGTAG, "not test");
 }
}

うん、こんなレイアウトのアプリはありえないね。

というのは置いといて…

おもむろにEditTextに改行を加えていくとこうなります。



AdViewが消えます。

その時Logcatにはこんな表示が

Not enough space to show ad! Wants: <480, 75>, Has: <480, 69>

ああ、表示領域が足りなくなったんですね。そらしゃーない。

んじゃー、表示できる領域がまた出来れば復活しますよね~



戻りません…

まあ再度adLoad呼べばいいんですが、そのタイミングがわかんないですよね。

ってことで AdListener をインプリメントすれば何かわかるんじゃないかな~

と思い、こんな感じに修正

public class Test extends Activity implements AdListener {

 /*中略*/

 public void onDismissScreen( Ad arg0) {

  Log.d( AdRequest.LOGTAG, "onDismissScreen");

 }


 public void onFailedToReceiveAd( Ad arg0, ErrorCode arg1) {

  Log.d( AdRequest.LOGTAG, "onFailedToReceiveAd");

 }


 public void onLeaveApplication( Ad arg0) {

  Log.d( AdRequest.LOGTAG, "onLeaveApplication");

 }


 public void onPresentScreen( Ad arg0) {

  Log.d( AdRequest.LOGTAG, "onPresentScreen");

 }


 public void onReceiveAd( Ad arg0) {

  Log.d( AdRequest.LOGTAG, "onReceiveAd");

 }
}

とりあえず何か返ってくるだろってことで期待しました。

が、消えるタイミングでは何も来ない…



えー、じゃあAdView拡張してなんかそれっぽいやつ(名前だけで適当に判断)Overrideしてイベント収集とか??

/**
 * とりあえずイベント収集
 */
class WrapAdView extends AdView {

 public WrapAdView( Activity activity, AdSize adSize, String adUnitId) {

  super( activity, adSize, adUnitId);
 }


 @Override
 public boolean dispatchPopulateAccessibilityEvent( AccessibilityEvent event) {

  Log.d( AdRequest.LOGTAG, "dispatchPopulateAccessibilityEvent:" + event);
  return super.dispatchPopulateAccessibilityEvent( event);
 }


 @Override
 public void dispatchWindowVisibilityChanged( int visibility) {

  Log.d( AdRequest.LOGTAG, "dispatchWindowVisibilityChanged:" + visibility);
  super.dispatchWindowVisibilityChanged( visibility);
 }


 protected void dispatchVisibilityChanged( View changedView, int visibility) {

  super.dispatchVisibilityChanged( changedView, visibility);
  Log.d( AdRequest.LOGTAG, "visibility:" + visibility);
 }


 protected void onWindowVisibilityChanged( int visibility) {

  super.onWindowVisibilityChanged( visibility);

  switch( visibility) {
  case VISIBLE:
   Log.d( AdRequest.LOGTAG, "VISIBLE");
   break;
  case INVISIBLE:
   Log.d( AdRequest.LOGTAG, "INVISIBLE");
   break;
  case GONE:
   Log.d( AdRequest.LOGTAG, "GONE");
   break;
  }

 }


 protected void onVisibilityChanged( View changedView, int visibility) {

  super.onVisibilityChanged( changedView, visibility);

  switch( visibility) {
  case VISIBLE:
   Log.d( AdRequest.LOGTAG, "VISIBLE");
   break;
  case INVISIBLE:
   Log.d( AdRequest.LOGTAG, "INVISIBLE");
   break;
  case GONE:
   Log.d( AdRequest.LOGTAG, "GONE");
   break;
  default:
   Log.d( AdRequest.LOGTAG, "ERR:" + visibility);
  }
 }
}

結果何も取得できず!!

( ´∀`)Σ⊂(゚Д゚ ) なんでやねん!

ちなみにレイアウト側を弄るとそもそもIMEの下に隠れるとかなくなりますが…

でもなんか釈然としない。

あー、やっぱりレイアウトに関してもっと勉強せんと駄目なんだろうなぁ…

ま、別にたまたま気がついただけで逃げ方は幾らでもありそうですが、

必ずディスプレイの下側にAdViewを配置して、IME表示時は隠れるようにしたい!!

とかになったらどーすんだろ。

IMEの表示非表示とかどうにかしてどうにかなるのかな…と思ってググったらぽいのがありました。

http://y-anz-m.blogspot.com/2010/12/androidonscreen-input-methods.html

上記を参考にして上手いことゴニョゴニョすれば何とかなりそうですね。

結論:やっぱりレイアウトに関して勉強すれば幾らでも回避できそう

メデタシメデタシ…

なのかな?

例の警告発生時(消えた事自体)のイベント取得方法知っている方居ましたら教えてください。

2011年6月15日水曜日

AdMobテストモードを使ってみた

前回はとりあえず表示だけしてみました。

だけど表示位置の確認やそもそもの動作確認したいですよね。

というかそれしないと駄目だろ。

という開発者のためのテストモードです。

てかさー、AdMobさんさー、もっとテストモードに関して分かりやすく書いてくれよ…

前回と全く同じ環境ですが、一応動作確認環境を書いておきます

端末:X06HT(Desire)

OS:2.2(公式っつーかrootも取ってない)

AdMobSDK:Ver 4.1.0

特にAdMobのSDKのバージョンが古いと、全くもって導入方法が変わるので注意


使用API

  • AdRequest.addTestDevice or setTestDevices
  • AdView.loadAd

XMLベースの場合

残念ながらXMLだけでレイアウトも書いてテストモードで動作ってのは出来なそうです。
そんなに追っかけてないから嘘かもしれませんがw

http://code.google.com/intl/ja/mobile/ads/docs/android/banner_xml.html#lookupandload

さて、自前でロードする(loadAdを呼んで広告表示させる)場合、上記の Lookup and Load 項目にあるように

・ads:loadAdOnCreate="true"
を削除するか false を指定する必要があります。

それが完了したらとりあえず下記のようなソースを書きます。

下のソース上では、レイアウトが記載されたxmlはmain.xmlという前提です。

当然パブリッシャーIDもxml上に書かれています。

public void onCreate( Bundle savedInstanceState) {

 super.onCreate( savedInstanceState);
 setContentView( R.layout.main);

 initAdmobLoadResView();

}


private void initAdmobLoadResView() {

 AdView adView = (AdView) findViewById( R.id.adView);
 AdRequest adRequest = new AdRequest();

 adRequest.addTestDevice( AdRequest.TEST_EMULATOR); // ※

 if( adRequest.isTestDevice( this)){
  Log.d( AdRequest.LOGTAG, "test");
 }else{
  Log.d( AdRequest.LOGTAG, "not test");
 }
 adView.loadAd( adRequest);

}

上記をとりあえず動作させ、Logcatを見ると…

「エミュレータ」ならとりあえず 「test」という文字列が表示されるでしょう。
(まあエミュレータの重さにうんざりしているので、確認してないんですけど。)

そして広告がテスト広告になっているのが確認できるかと思われます。

じゃあ、実機だとどうなのか…

多分普通に広告が表示されるか、表示に失敗して何も起きないかどっちかです。

Logcat的にはこんな感じ



で、Logcat上のこんな部分に注目しましょう。
To get test ads on this device, call adRequest.addTestDevice("hogehoge");

なにやら変なIDっぽいものが書いてあります。

これをおもむろにコピーして上記ソースの※部分を

・AdRequest.TEST_EMULATOR → "hogehoge"

に置き換え。

またここで得たhogehogeは端末毎で異なるようです。多分。

少なくとも会社の人の端末借りたら「not test」って返ってきましたし。

ついでに

if( adRequest.isTestDevice( this)){
 Log.d( AdRequest.LOGTAG, "test");
 adView.loadAd( adRequest);
}else{
 Log.d( AdRequest.LOGTAG, "not test");
}

としておくと安全面でいいかも

なお、最初に上記のようなソースにしなかったのには理由が。
loadAdを呼ばないと上記のLogcatが表示されないんですね。

最初からこの状態だと「not test」が表示されるだけで後は何も起こりません。

ちなみに…

addTestDeviceのjavadocはこんな感じです。

public void addTestDevice(String testDevice)

Causes test ads to be returned to a device. Look at logcat while requesting an ad to see how to return test ads to a device. There will be a log message with the code needed to add the current device to the list of test devices. For example:

(String testDevice)

この部分「だけ」をみて、TelephonyManagerつかってgetDeviceID呼べばいいのか?

とか思って実際にそんなソース書いてテストモードに移行できずに悩んでいたのは秘密

で、肝心のドキュメントはこちら
http://code.google.com/intl/ja/mobile/ads/docs/android/intermediate.html#addtestdevice

実にソースを含め5行でまとまっています。

5行でね…


レイアウト自前実装の場合はもう書かなくてもいいですよね。

loadAdの前にaddTestDeviceを呼んでやればOKです。

てかさー、testDeviceのIDですか?

取得できるようなAPIとか開けておいて欲しいです…


おまけ debuggable trueの場合のみテストモード
実際やるとしたらこんなソースになるんでしょうか。

public void onCreate( Bundle savedInstanceState) {

 super.onCreate( savedInstanceState);
 setContentView( R.layout.main);

 initAdmobLoadResView();

}


private void initAdmobLoadResView() {

 AdView adView = (AdView) findViewById( R.id.adView);
 AdRequest adRequest = new AdRequest();

 // debuggable が trueの場合
 if( ApplicationInfo.FLAG_DEBUGGABLE == (ApplicationInfo.FLAG_DEBUGGABLE & getApplicationInfo().flags) ){

  adRequest.addTestDevice( "hogehoge");

  if( adRequest.isTestDevice( this)){

   Log.d( AdRequest.LOGTAG, "test");
   adView.loadAd( adRequest);

  }else{

   Log.d( AdRequest.LOGTAG, "not test");
  }

 }else{
  adView.loadAd( adRequest);
 }
}

次回
・適当に配置したら色々困って解決策募集中
です。

2011/06/15現在答え見つかってないので、誰か教えてくださいな。

AdMobを使ってみた

AdMobといえば、よくあるAndroidアプリの上とかにくっついている広告です。

アプリを提供したいけど…とても有料アプリとしては使ってくれなそう…
でも収入も得たい!

そうなるとこういった選択肢しかないでしょうね。





私の動作確認環境

端末:X06HT(Desire)
OS:2.2(公式っつーかrootも取ってない)
AdMobSDK:Ver 4.1.0

特にAdMobのSDKのバージョンが古いと、全くもって導入方法が変わるので注意





必須準備

SDKの用意…
AdMob行って登録して適当に貰ってきましょう。
ついでにパブリッシャーIDなるものも適当に貰ってきましょう。
http://jp.admob.com/

AdMob SDK download とかでググれば、親切丁寧に教えてくれているサイトも見つかるかと。


続いて…以下の通りに作業を進めるだけw
http://code.google.com/intl/ja/mobile/ads/docs/android/fundamentals.html

ここで忘れてはいけないのは以下二つ
http://code.google.com/intl/ja/mobile/ads/docs/android/fundamentals.html#adactivity
http://code.google.com/intl/ja/mobile/ads/docs/android/fundamentals.html#permissions

Permissionの設定は、広告データ取ってきたり広告に飛んだりするので
当然必要ですが、思わず忘れてしまいそうなのが、
com.google.ads.AdActivity というアクティビティを宣言すること
だと思います。

なお、上記のドキュメントの通りきっちり書きましょう。
AdActivityを宣言し忘れたり、configChangesの内容を端折ったりすると、コンパイル段階でエラーになりましたw





XMLだけで表示する場合

http://code.google.com/intl/ja/mobile/ads/docs/android/banner_xml.html#defineadview

上記の 「Defining a com.google.ads.AdView」の項目にあるXMLをコピって終了。
コピった先がmain.xmlとかなら、あとはsetContextView( R.layout.main)を適当に呼べばよし。
ads:adUnitIdには、AdMobで発行されたパブリッシャーIDを突っ込むのを忘れずに。





自前実装

http://code.google.com/intl/ja/mobile/ads/docs/android/fundamentals.html#addadview

といってもXMLで書くのをソースで書いて、loadAdを呼ぶだけ。
本当に上記の通り。
AdViewを生成するときに、コンストラクタにAdMobで発行されたパブリッシャーIDを突っ込むのを忘れずに。





上記を実行すると見たことのある、あの広告画面が表示されます。
メデタシメデタシ

とは終わらない…

ここまでの内容だと、本当にドキュメントを流し読みすりゃ出来る内容です。
ぶっちゃけAdMob的に問題だろ?と思うのは…

テストモードに関しての記述が少なすぎること。

てっきりAdMobのサイト上で設定するとかMarketに登録されるまでテスト広告がでるんでしょ?
とか思ってましたよ。


というわけで次は肝心のテストモードに関してです。

2011年6月12日日曜日

統合環境私的備忘録

家でも職場でもeclipse様様な状態でAndroidプログラムしてます。こんにちは。

某BREWとかBREWとかBREWとかだとまあ大体エディター直打ちやってますが、正直統合環境使えるなら使いたいところですね。

え、VC使えって?いや、もうBREWは見なかったことに…

そんなeclipse様に関する私的備忘録。

なんで書こうかと思ったかというと…

workspace切り替えたりなんかアップデートしたり家と会社の環境を合わせたりする為の備忘録的な意味合いで…

え、設定ファイル持ち歩けってか…

うん、多分それが一番正しいと思います。


といってもそんなにeclipseを端から端までの知り尽くしているわけではないです。

あくまで私が便利だと思い込んでいるところとかだけ…。


フォーマッター設定

人のソースを受け継いだり、webからありがたーくサンプルを頂いたりすると…

他人と私ではソースの書き方が違ったり、webからコピーするとインデントされなかったり…

あれをイチイチ手直しなんかしてらんないですよね~

そんな時は「Ctrl + I」とか「Ctrl + Shift + F」とか押すと幸せになれますよね。
→編集のどっかの項目だったと思いますが、ショートカットしか覚えていない

eclipseに限らず、インデントの修正やフォーマットに沿っての修正をやってくれるというのは統合環境の機能の中で最高に好きな機能の一つです。

例えばこうなる

class Test{
 private int mTest = 0;

 Test(int i){
 mTest = i;
 }

 public int getMTest(){
 return mTest;
 }
 }

上のようなのをとりあえずコピーするとこんな感じ



Ctrl + Shift + F を押すと(私の環境は)こうなる



す、素晴らしい…

素晴らしいんだけど、これだって自分の普段のフォーマットとは違う可能性があるわけで…

ということで、このフォーマットを設定するのが
・ウィンドウ→設定→Java→コード・スタイル→フォーマッター
です。

元々ある設定を自分好み改変して、設定ファイルをExportしておけば、家でも会社でも素晴らしいフォーマッター生活がエンジョイできます。

ちなみに保管アクションで、終了時にフォーマット掛けてくれるような設定も可能。
私はなんとなくやってませんが。

てかさー、大体の統合環境ってこういう機能満載なんだから…

会社でちゃんとフォーマット決めて使おうぜ!!

と思っていますが、割とエディター大好きな方が多いので浸透しません…

まあちなみに万能ではないです。


// これが
if( bTest)
 bTest = false;


// こうはならない
if( bTest){
 bTest = false;
}

この辺はフォーマット後諦めてエディターで正規表現でgrep掛けて置き換えしてますが…

なんかいい方法無いでしょうか?

2011/07/05 追記
クリーンアップ側の設定で可能でした。


以下ほんとに備忘録

Q:パッケージエクスプローラ上でsvnとかのファイルがいて、どうでもいいパッケージが表示されるんだけど…

A:

  • ウィンドウ→設定→Java→外観→パッケージ・エクスプローラおよびプロジェクト・エクスプローラの階層…を折り畳むにチェック入れる
  • ウィンドウ→設定→Java→コンパイラー→ビルド→出力フォルダーのフィルターするリソースに「.svn/」とか書き足しておく

Q:Androidプロジェクトにてgen(出力先)フォルダ内のソースに警告でてうざいんだけど…

A:ウィンドウ→設定→Java→FindBugs→フィルター・ファイルでExclude filter fileにgenを省くように書いたxml読ませる


コメントでも書きましたが、自分自身できてませんでした。

むしろ誰か教えてください

Q:TODOとか以外にタスク・タグにコメントが乗るようにしたい

A:ウィンドウ→設定→Java→コンパイラー→タスク・タグを好きに弄る

この辺が環境切り替えたときにやる(やった)ことですかね。


他に
・お前この設定使ってないのかよ、情弱乙www
とかあったら教えてください。