4

画面の向きが変わってマルチスレッドが実行されているとき、Adview に問題があることがわかりました。これはAdviewのバグかもしれないと思います。この問題は、アプリケーション内のすべての Web ビューに影響します。Web ビューはコンテンツの読み込みを停止します。つまり、空白または以前に表示されていたコンテンツが表示されます。

テスト環境は

プラットフォーム: Google Nexus S + Android 4.1.2 (このプラットフォームだけでなく、他の多くのプラットフォーム、エミュレーターも影響を受けます)

Ads SDK: 6.4.1 (同じ問題がある Ads SDK 4.1.1 もテストしました)

この問題を再現する方法は、

  1. 次のマニフェスト、main.xml レイアウト、helloAndroid.java、および Ads SDK (6.4.1 以前のバージョン) を使用して Android プロジェクトを構築します。

  2. 上記のプラットフォームで HelloAndroid プロジェクトを実行するか、他のプラットフォームでも影響を受ける可能性のあるエミュレーターで実行します。

  3. アプリの起動後、「OnCreate 関数が呼び出されました」と表示されます。また、コンテンツが読み込まれる時間も表示されます。その間、広告は画面の上部に表示されます。

  4. ここで、[スレッドの計算を開始] ボタンをクリックすると同時に、画面を回転させて向きを変更し、すぐに向きを変更します。その間、最後の計算タスクが終了した直後に [スレッドの計算を開始] ボタンを連続してクリックします。これらのアクションを数回繰り返すと、Web ビューがリロードされないことがわかります。そのテキストは、画面を回転させるかどうかに関係なく、常に「バックグラウンド計算スレッドが完了しました」です。(「スレッド計算の開始」ボタンをクリックするかどうかに関係なく、そのテキストは「構成が変更されました」となる場合もあります)。Webview に表示される時刻も更新されません。広告は表示されません。

ログ ファイルから、次のような多くの広告エラーを確認できます。

11-17 11:51:11.254: I/Ads(7411): URL の取得中に AdLoader が 60000 ミリ秒後にタイムアウトしました。

11-17 11:51:11.254: I/Ads(7411): onFailedToReceiveAd(ネットワーク エラーが発生しました。)

例外も発生しますが、この例外は上記のエラーが発生した後に表示されます。

11-17 11:53:14.597: W/Ads(7411): AdWebView でデータをロード中にエラーが発生しました:

11-17 11:53:14.609: I/Ads(7411): 以下がキャッチされ、処理されました:

11-17 11:53:14.609: 私/広告 (7411): java.lang.NullPointerException

11-17 11:53:14.609: 私/広告 (7411): android.webkit.WebViewClassic.loadDataWithBaseURL (WebViewClassic.java:2564) で

11-17 11:53:14.609: 私/広告 (7411): android.webkit.WebView.loadDataWithBaseURL (WebView.java:842) で

11-17 11:53:14.609: 私/広告 (7411): com.google.ads.internal.AdWebView.loadDataWithBaseURL (SourceFile:229) で

11-17 11:53:14.609: 私/Ads(7411): com.google.ads.internal.c$c.run(SourceFile:164)

11-17 11:53:14.609: I/広告 (7411): android.os.Handler.handleCallback (Handler.java:615) で

11-17 11:53:14.609: I/Ads(7411): android.os.Handler.dispatchMessage(Handler.java:92) で

11-17 11:53:14.609: I/Ads(7411): android.os.Looper.loop(Looper.java:137)

11-17 11:53:14.609: 私/広告 (7411): android.app.ActivityThread.main (ActivityThread.java:4745) で

11-17 11:53:14.609: I/Ads(7411): java.lang.reflect.Method.invokeNative(ネイティブ メソッド) で

11-17 11:53:14.609: I/広告 (7411): java.lang.reflect.Method.invoke (Method.java:511) で

11-17 11:53:14.609: 私/広告 (7411): com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run (ZygoteInit.java:786) で

11-17 11:53:14.609: 私/広告 (7411): com.android.internal.os.ZygoteInit.main (ZygoteInit.java:553) で

11-17 11:53:14.609: 私/広告 (7411): dalvik.system.NativeStart.main (ネイティブ メソッド) で

この問題は、次の観察結果に基づいて、webView またはスレッド プログラミングではなく、AdView が原因であると考えています。

  1. webView を別のアクティビティに配置した場合、つまりマルチスレッド アクティビティにボタンと adView のみが含まれている場合でも、上記の再現手順の後にこの問題が発生することがわかりました。そして、問題が発生した後、webView を含む他のアクティビティを移動しましたが、それでも読み込みは停止します。つまり、問題を引き起こすのは webView ではありません。

  2. 計算スレッドは非常に単純で、UI 操作は含まれていません。広告の読み込みの開始と停止は、常にメイン スレッドで行われます。

コードは非常に単純です。マニフェスト ファイルは次のとおりです。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.example.helloandroid"
      android:versionCode="1"
      android:versionName="1.0">
    <uses-sdk android:minSdkVersion="7" />
    <!--  uses-permission android:name="android.permission.INTERNET"/-->

    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".HelloAndroid"
                  android:label="@string/app_name"
                  android:configChanges="orientation|keyboardHidden|screenSize">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name="com.google.ads.AdActivity"
              android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize"/>
    </application>
</manifest>

唯一のレイアウト ファイルは次のとおりです。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:ads="http://schemas.android.com/apk/lib/com.google.ads"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
    <LinearLayout 
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:id="@+id/adsHolder" >
    </LinearLayout>

    <android.webkit.WebView
        android:id="@+id/webview_show_something"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_above="@+id/button1"
        android:layout_below="@+id/adsHolder"
    ></android.webkit.WebView>

    <Button
        android:id="@+id/button1"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:text="Start Calculating Thread" />

</RelativeLayout>

HelloAndroid.java ファイルは次のとおりです。

package com.example.helloandroid;

import java.text.DateFormat;
import java.util.Date;

import com.google.ads.AdRequest;
import com.google.ads.AdSize;
import com.google.ads.AdView;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;

public class HelloAndroid extends Activity {
    // Need handler for callbacks to the UI thread
    public Handler mHandler;

    public WebView mwebView;

    public AdView madView;

    public Thread mthread = null;
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        mHandler = new Handler();   // handler is attached to the UI thread.

        Button btn = (Button) findViewById(R.id.button1);
        btn.setOnClickListener(new OnClickListener(){

            @Override
            public void onClick(View v) {
                final ProgressDialog dlgProgress = ProgressDialog.show(HelloAndroid.this, "Please wait",
                        "Background calculating ...", true);
                mthread = new Thread(new Runnable(){

                    @Override
                    public void run() {
                        for (int idx = 0; idx < 10000; idx ++)  {
                            for (int idx1 = 0; idx1 < 10; idx1 ++)  {
                                int a = idx + idx1;
                                a ++;
                            }
                        }
                        mHandler.post(new Runnable()    {

                            @Override
                            public void run() {
                                dlgProgress.dismiss();
                                if (madView != null)    {
                                    madView.loadAd(new AdRequest());
                                }
                                String currentDateTimeString = DateFormat.getDateTimeInstance().format(new Date());

                                mwebView.loadDataWithBaseURL("http://",
                                        "<html><body><h1>Background calculating thread done.</h1><p>" + currentDateTimeString + "</p></body></html>",
                                        "text/html","utf-8","");
                                mthread = null;
                            }
                        });
                    }
                });
                if (madView != null)    {
                    madView.stopLoading();
                }
                mthread.start();

            }

        });

        mwebView = (WebView)findViewById(R.id.webview_show_something);
        mwebView.setVerticalScrollBarEnabled(true);
        mwebView.setHorizontalScrollBarEnabled(true);
        mwebView.getSettings().setBuiltInZoomControls(true);
        mwebView.setWebViewClient(new WebViewClient());

        String currentDateTimeString = DateFormat.getDateTimeInstance().format(new Date());

        mwebView.loadDataWithBaseURL("http://",
                "<html><body><h1>OnCreate function called.</h1><p>" + currentDateTimeString + "</p></body></html>",
                "text/html","utf-8","");
        startLoadingAds();

    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        // because it is smart_banner, adview has to be dynamically generated to fit landscape or portrait screen.
        stopLoadingAds();
        if (mthread == null)    {   // only if calculating thread finishes we start to load ads.
            startLoadingAds();
        }
        String currentDateTimeString = DateFormat.getDateTimeInstance().format(new Date());

        mwebView.loadDataWithBaseURL("http://",
                "<html><body><h1>Configuration changed.</h1><p>" + currentDateTimeString + "</p></body></html>",
                "text/html","utf-8","");
    }

    public void stopLoadingAds()    {
        // reset the adView.
        if (madView != null)    {
            madView.stopLoading();
            ViewGroup viewGroup = (ViewGroup) madView.getParent();
            if (viewGroup != null)
            {
                viewGroup.removeView(madView);
            }
            madView.removeAllViews();
            madView.destroy();  // not required.
            madView = null;
        }
    }

    public void startLoadingAds()   {
        LinearLayout layoutAdView = (LinearLayout)findViewById(R.id.adsHolder);
        layoutAdView.removeAllViews();
        madView = new AdView(this, AdSize.SMART_BANNER, "ca-app-pub-9004844319824679/3238161316");
        if (madView != null)    {
            layoutAdView.addView(madView, new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
            madView.loadAd(new AdRequest());
        }
    }
}
4

0 に答える 0