0
Thumbsup

いい質問だ

0

Thumbsdown

うーん

Androidモジュールで広告SDKからのコールバック取得ができない

m278
m278 0

投稿日:2016-05-10 12:38:03

お世話になります。
現在、広告SDKから広告データをリストで受け取るためのAndroidモジュールを開発しています。Titanium SDKバージョンは4.1.0GAです。
本来の動きとしては、広告取得メソッド-getAdList()を呼ぶとコールバックに広告データが返却
されるはずで、これはAndroidアプリで確認しました。
しかしモジュール内でgetAdList()を呼ぶとコールバックに広告データが渡ってこない(nullが返却される)状態です。
viewとviewProxyを使うのか?とかいろいろ試行錯誤していますが壁にぶつかっている状態です。
SDKからのコールバックを受け取る方法をご存知の方いらっしゃいましたらご教示くださいませ。

なお、広告SDKのAndroid実装用資料にはMainActivityのonCreate()内で

 adSdk.getAdList(new OnGetAdListener() {
    // コールバック
    @Override
    public void onGetAd(List<ad> ads) {
   // List<ad> adsに広告データが渡される
    }
 });

とあるので、これを下記のようにモジュール化しました。

@Kroll.method
public void adList(final KrollFunction callback) 
    {
        adSdk = XAdSdk.getInstance();
        adSdk.initialize(this.getActivity().getApplicationContext());
        adSdk.getAdList(new OnGetAdListener() {
                public void onGetAd(List<ad> ads) { <-このadsがnullになってしまう
                 KrollDict data = new KrollDict();
                 if(ads != null){
                     String[] adsStr = ads.toArray(new String[ads.size()]);
                     data.put("ads", adsStr);
                 }else{
                     data.put("ads", null);
                 }
                 callback.call(getKrollObject(), data);
                }
        });
    }

デバッグするとadSdkのインスタンスは生成されています。が、onGetAd()で得られるadsはnullとなってしまいます。
モジュールを呼び出しは以下のとおりです。
module = require('ID');
module.adList(function(e){
        if(e.ads == null){
            Ti.API.info("!! ads is null !!");
        }else{
            Ti.API.info("!! GET ads !!");
        }           
});

何卒よろしくお願いいたします。


回答

m278
m278
0

Thumbsup

いい回答

1

Thumbsdown

うーん



okhttpを2.xに変えたところ、adsの値が取ることができました!!
yagi_様、ありがとうございます!

今回、このokhttpのバージョンの問題とサービスの追加を行うことが解決策であったわけですが、腑に落ちない点がサービスの追加でして、Androidアプリ単体で広告取得するときにはその記述は必要なかったのに、モジュールから広告取得を行う場合にはそれが必要だったということです。

Titaniumのモジュールから外部SDKをコールする際の手順として、そのサービスの起動を追加するという事例が(私が調べた中では)見つけられなかったのですが、今回私が利用した広告SDKがたまたま内部でサービスを起動する処理があり、tiapp.xmlにサービスの記述を行う必要があった、ということなのでしょうか?


ですね。AndroidManifestへのServiceの追加はネイティブだろうが関係なく必要なことだったんだと思います。 --- yagi_

そうなのですね。ddmsでのログ確認、勉強になりました。yagi_様のアドバイスのおかげで無事解決に至り、たいへん感謝しております。ありがとうございました。 --- m278

yagi_
yagi_
2540
Tcad_icon Tcmd_icon Tce_icon

Thumbsup

いい回答

1

Thumbsdown

うーん



Mavenレポジトリからokhttp-3.2.0.jarを取得したところokhttp3/OkHttpClient.classが見つかりましたがcom.squareup.okhttp.OkHttpClientはありませんでした。

$ jar tf ~/Downloads/okhttp-3.2.0.jar |grep -i httpclient.class
okhttp3/OkHttpClient.class

http://stackoverflow.com/questions/36800934/package-path-for-okhttp3-okhttpclient-or-com-squareup-okhttp-okhttpclient

こちらによれば2.xとはパッケージ名が変わってしまったようです。おそらくokhttpのバージョンのミスマッチではないかと思います。


yagi_
yagi_
2540
Tcad_icon Tcmd_icon Tce_icon

Thumbsup

いい回答

0

Thumbsdown

うーん

Contextの取得の仕方の問題じゃないかと思います。ApplicationのContextが必要なんですよね?

http://qiita.com/yagi_/items/1775c6159dc2011065be#context%E3%82%92%E6%89%B1%E3%81%86

よく使うのが、このようにAndroidのLifecycleイベントを使ってしまうやり方です。

private KrollDict data;

@Kroll.onAppCreate
public static void onAppCreate(TiApplication app){
  adSdk = XAdSdk.getInstance();
  adSdk.initialize(app);
  adSdk.getAdList(new OnGetAdListener() {
      public void onGetAd(List<ad> ads) {
          data = new KrollDict();
          if(ads != null){
            String[] adsStr = ads.toArray(new String[ads.size()]);
            data.put("ads", adsStr);
          }else{
            data.put("ads", null);
          }
      }
    });
}

@Kroll.method
public KrollDict getAds(){
  return data;
}

回答して、ついでに通知の機能を作りました --- yagi_

返信ありがとうございます。いただいたURLの記事を当初から参考にさせていただいており、コメントいただいたようにonAppCreate()の中で ```adSdk.initialize(app);``` として試してもいるのですが、同様の結果でした。 ちょっと混乱しているので確認したいのですが 1.SDKからのコールバック(onGetAd())は受け取れている  ->で認識あっていますか? 2.onGetAd()の引数のadsには値が入ってこない 以上のことから、SDK内部の処理でエラーなりなんらかが起きていて値をコールバックにセットできていない、ということと捉えて良いのでしょうか? それともSDKからコールバックでモジュールに値を渡すことってできないのでしょうか? --- m278

ああ、なるほど。切り分けのためにLog.d(ads)してそもそもデータを取得できているのか確認してもらえますか? --- yagi_

はい、Logで確認するとadsはnullとなります。 --- m278

モジュールは関係なくAndroidアプリ単体で同じように実装すると、adsは正常に広告データが入ってきます。やはりモジュールからgetAdList()を呼ぶことに問題があるのでしょうか。。 --- m278

モジュールもTitaniumの他の機能も等価なので、実装に必要な情報が足りていない問いっただけの問題だと思います。onGetAdsが空なので、MainActivityのonCreate内で実行しなければいけないというのがポイントかなと思います。 --- yagi_

yagi_
yagi_
2540
Tcad_icon Tcmd_icon Tce_icon

Thumbsup

いい回答

0

Thumbsdown

うーん

@Kroll.onAppCreate
    public static void onAppCreate(TiApplication app) 

は実際にはアプリの起動中に実行されモジュールがロードされる前に呼ばれます。ここでKrollFunctionのコールバックを設定しても呼び出されないはずです。

なので、onAppCreateを利用する場合は取得するデータ自体を別の方法で呼び出すようにします。

private KrollDict data;
@Kroll.onAppCreate
public static void onAppCreate(TiApplication app) {
  adSdk = XAdSdk.getInstance();
  adSdk.initialize(app);
  adSdk.getAdList(new OnGetAdListener() {
    public void onGetAd(List<ad> ads) {
      data = new KrollDict();
      //ここでadsがnullなら何か別の問題がある
      if(ads != null){
        Log.d(LCAT, "[DEBUG]: yay! ads is not null!");
        //ここでJavaScriptのcallbackは呼べないので一旦インスタンス変数に格納しておく
        String[] adsStr = ads.toArray(new String[ads.size()]);
        data.put("ads", adsStr);  
      }else{
        Log.d(LCAT, "[DEBUG]: ads is null");
      }
    }
  });
}

なるほどです。ありがとうございます。「MainActivityのonCreate内で実行」と同等のことをモジュールで実装する方法はあるのでしょうか。。? --- m278

上の例がそうです。ほぼ同等っていう感じです。 --- yagi_

となりますと、上の例でadsが取れない、というのはSDK側の問題でコールバックにadsがセットできていないという認識で良いのでしょうか?つまりモジュール側ではどうしようもできない、と。 --- m278

広告SDKの資料を再確認したところ、「広告を取得したいActivityのonCreate()でgetAdList()を呼ぶ」とあったので、MainActivityでなくても良いようです。後からの情報で申し訳ありません。。ですのでモジュール側の実行方法については問題なさそうです。本件がSDK側の問題と切り分けられればそれで今後の実装方針を見直すのですが、、悩ましいです。 --- m278

問題がSDKだけなのかどうかはこちらではわからない(IDをセットしたりする箇所があったり色々するかもしれない)のですが、onCreateで動くなら上のコードで問題ないはずですね。他に設定箇所はありませんか? --- yagi_

m278
m278
0

Thumbsup

いい回答

0

Thumbsdown

うーん

設定箇所としては「必須ライブラリの追加」と「IDをAndroidManifest.xmlのmeta-dataへ設定」の二つがあり、前者はビルドパスに追加済みで後者についてはtimodule.xmlのandroidタグに以下のように設定しています。必要かはわからなかったのですがtiapp.xmlにも同じ内容を記述しています。

<android xmlns:android="http://schemas.android.com/apk/res/android">
        <manifest android:installLocation="auto">
            <uses-permission android:name="android.permission.INTERNET" />
            <application
                android:debuggable="false" android:largeHeap="true">
                <meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version"/>
                <meta-data android:name="media_id" android:value="xxxxxxxxxxxxxxxxxxx"/>
            </application>
            <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="21"/>
        </manifest>
    </android>

build/android/AndroidManifest.xmlの内容を確認して、もし必要な情報がなければcleanしてみてください --- yagi_

build/android/AndroidManifest.xmlの内容を確認しましたが、必要なID情報は含まれておりました。 ちなみに単体のAndroidアプリで確認すると、このID情報が仮に取得できなかった場合でもadsはnullではなくsizeが0のadsが返却されました。ですのでadsがnullというのはなにかまた違う問題が原因なのかな、という気がします。 --- m278

はい、違う問題ですね。何かエラーが出ていないか確認した方がいいと思います。Titaniumなら--log-level traceでビルドしたり、あるいはddmsでログを確認したらどうなりますか? --- yagi_

m278
m278
0

Thumbsup

いい回答

0

Thumbsdown

うーん

ddmsでログを見るとadSdk.initialize(app);のタイミングで

Unable to start service Intent {comp={com.sample/io.ads.xad_sdk.XAdServices}} : not found

と出ていました!この見つからないと言われているサービスについては初めて目にするものでしたが、念のためtiapp.xmlに
<service android:name="io.ads.xad_sdk.XAdServices" />

と追加し、再度実行すると今度は別のエラーが。
java.lang.ClassNotFoundException: Didn't find class"com.squareup.okhttp.OkHttpClient" on path

okhttpは今回の広告SDKでは必須ライブラリなので、okhttp-3.2.0.jarモジュール側のlibに配置し、モジュール側のビルドパスにも追加しています。

モジュールで必要なjarは、モジュールのビルドパスに追加する以外にもアプリ側への配置等必要なのでしょうか?
またtiapp.xmlに追記したサービスの記述は必要なのでしょうか?導入資料にサービスに関する記述がなかったためいまいちわかりません。。


ログインすると回答することができます。