2010年4月3日 星期六

【分享】- 如何在 Android 程式中加入不會因網路問題而出現錯誤網頁視窗的 AdSense Mobile 服務?

由於有個 Google 員工在 Google AdSense 論壇發表了一篇令人疑惑的文章,詳見這裡,所以,請夥伴們就先將此篇文章當作是 WebView 元件程式設計的參考吧 ^__^  \\\

Google AdSense Mobile 服務必須在有數據網路連線時才有作用,但在 Android 手機的應用程式中,其實有許多是下載後就可使用,不用一直連著數據網路的 (WiFi 還好, 但行動網路費用很貴),於是乎在使用者下載完 Android 程式到手機中並關閉數據網路 (WiFi 或 行動網路) 後,在執行程式時,問題就來了! 原本該顯示 AdSense Mobile 的地方,會出現找不到網頁的錯誤訊息,破壞了整個程式的使用者介面,怎辦呢?




其實,在坊間的書籍是有範例的,就是先偵測連網有沒問題,再決定要不要載入 AdSense Mobile,以下是漁郎東拼西湊出來的完整範例程式碼,裡面有註解說明,有興趣的伙伴就參考參考吧!如有更好的方法,請別吝於告訴漁郎喔 ^__^ 。

前置動作:請先申請兩個 Google App engine 的 Application ID,一個是 AdSense Mobile 要使用的行動網頁,一個是測試連線要用的空網頁。您如不清楚怎回事,請參考漁郎的前作「Eclipse、App engine、AdSense Mobile」與「Android & AdSense Mobile」及「App engine、Analytics、Android Market」。

程式碼一:設定檔 (AndroidManifest.xml),要加入 INTERNET 服務許可。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.e68club.android.AdSenseTest"
      android:versionCode="1"
      android:versionName="1.0">
    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".AdSenseTest"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

    </application>
    <uses-sdk android:minSdkVersion="3" />
    <uses-permission android:name="android.permission.INTERNET" />
</manifest>

程式碼二:佈局檔 (res/layout/main.xml)

<?xml version="1.0" encoding="UTF-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
      android:layout_height="fill_parent"
      android:orientation="vertical"
      android:gravity="center"
      >     
    <TextView
          android:id="@+id/TextView010"
          android:layout_width="fill_parent"
          android:layout_height="wrap_content"
          android:textSize="20sp"   
          android:textColor="#FFFF00"
          android:text="AdSense Mobile Connect Test"
      />
      <WebView
        android:id="@+id/AdSenseWeb01"
        android:layout_width="320px"
        android:layout_height="50px"
        android:layout_alignParentBottom="true"
      />     

</RelativeLayout>

程式碼三:主程式檔 (src/com.e68club.android.AdSenseTest/AdSenseTest.java)

package com.e68club.android.AdSenseTest;

import java.net.HttpURLConnection;
import java.net.URL;
import android.app.Activity;
import android.os.Bundle;
import android.webkit.WebView;
import android.widget.TextView;

public class AdSenseTest extends Activity {

// Google AdSense 行動網頁的網址 - SAMPLE - 請改為自己的網址
String mAdSenseWebUrl01 = "http://你的應用服務 ID.appspot.com";
  
// 測試用之空網頁的網址 - SAMPLE - 請改為自己的網址
String mConnectTestWebUrl01 = "http://應用服務 ID.appspot.com/";


// Google AdSense 使用的網頁瀏覽元件定義
WebView mAdSenseWeb01 ;


// 公用變數設定
private TextView TextView010;
 
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
     
        TextView010 = (TextView) this.findViewById(R.id.TextView010);

        TextView010.setText("AdSense Mobile 連網測試");
     
        // 測試手機是否具有連線 Google App Engine 的連線能力
        if(checkInternetConnection(mConnectTestWebUrl01,"utf-8") == true) {
            // Google AdSense 運作程式碼
            mAdSenseWeb01 = (WebView)findViewById(R.id.AdSenseWeb01);
            mAdSenseWeb01.getSettings().setJavaScriptEnabled(true);
            try {
                mAdSenseWeb01.loadUrl(mAdSenseWebUrl01);
            } catch(Exception e) {
                // 當作沒錯誤, 避免破壞程式運作時畫面
            }
        }
     
    }
 
    // 檢查網路連線是否正常之副程式
    public boolean checkInternetConnection(String strURL, String strEncoding) {
        // 此副程式之特性是僅用於連線測試, 不是開啟網頁,
        // 因此, Google Analytics 並不會納入分析報表中, 但 Google App Engine 會有記錄.
     
        // 最多延時 n 秒若無回應則表示無法連線
        int intTimeout = 5000; // 1000 = 1 秒
        try {
            HttpURLConnection urlConnection= null;
            URL url = new URL(strURL);
            urlConnection=(HttpURLConnection)url.openConnection();
            urlConnection.setRequestMethod("GET");
            urlConnection.setDoOutput(true);
            urlConnection.setDoInput(true);
            urlConnection.setRequestProperty("User-Agent",this.getPackageName()); // 自定訊息-程式名
            urlConnection.setRequestProperty("Content-type","text/html; charset="+strEncoding);
            urlConnection.setConnectTimeout(intTimeout);
            urlConnection.connect();
            if (urlConnection.getResponseCode() == 200) { // Code 回應為 200 表連線正常
                return true; // 函式回傳 true 值, 因連線成功.
            } else {
                return false; // 函式回傳 false 值, 因連線失敗.
            }         
        } catch (Exception e) {
          e.printStackTrace();
          return false; // 函式回傳 false 值, 因不明原因的執行期錯誤.
        }
    }
 
}

無法連網時的畫面:



可以連網時的畫面:


9 則留言:

  1. 請問一下, Android App到底能不能放WebView的廣告; 放了會不會被封鎖?
    不是只能放AdSense SDK的嗎?

    謝謝

    回覆刪除
  2. 漁郎曾經到盧老師的網站向盧老師詢問,老師的回答是:當然會違反 Google 的規定. 因此, 漁郎在網誌的相關文章前頭都加上了警語. 至於如朋友們還是將行動內容廣告放在 WebView 中呈現會不會被 Google 封了, 漁郎就沒嘗試過了. @@

    回覆刪除
  3. 请问如果我使用Webview显示一个网站,而那个网站拥有adsense广告,这被不被允许呢請問如果我使用Webview顯示一個網站,而那個網站擁有adsense廣告,這被不被允許呢?

    回覆刪除
    回覆
    1. 據漁郎所知:不行~~~ @@

      刪除
    2. 為什麽不行啊?我沒有像你這樣特意用webview放個adsense廣告。我使用webview打開一個網站,而那個網站有adsense廣告。如果這樣也不行的話,比如說我用webview打開別人的網站,而他/她的網站擁有adsense廣告,這樣就會導致他/她的adsense戶口被取消了?如果是這樣的話,那個人會不會太無辜了?

      刪除
    3. 您可能誤解漁郎的意思了!基本上,此ㄧ規定是針對在「自己」開發的APP上掛載用WebView掛載含有「自己」推播的AdSense廣告才「不行」~ 如果,是用 WebView 掛載別人的網頁,而那網頁掛載的 AdSense 廣告不是自己推播的,就沒問題.至於為何這樣?這是漁郎問過幾位前輩得到的答覆.還有,AdSense開發者論壇也有許多說明,請參考參考.

      刪除
    4. 安全第一。還是不要放比較好吧。

      刪除
  4. 我想請問一下webview顯示的網頁有沒有辦法跟電腦版的網頁一樣

    回覆刪除
  5. If you're looking for an excellent contextual ad network, I suggest that you try ExoClick.

    回覆刪除