2013年2月9日 星期六

使用GCM服務(六) 設計GCM應用程式(2)

在使用GCM服務(五) 設計GCM應用程式(1)文中已建立GCMIntentService程式框架,接著必須實作GCMIntentService類別程式碼。
(1). 在建構元中將在Google APIs Console建立Project編號當做Sender ID,傳給GCMBaseIntentService類別。

  public GCMIntentService(){
     super("Your_Sender_ID");
  }

(2). 向GCM Server註冊並取得裝置的registration Id後,GCMBroadcastReceiver會調用onRegistered(),在此須同步向訊息推播伺服器登錄裝置的registration Id。

  @Override
  protected void onRegistered(Context context, String regId) {
        /**
         * 撰寫程式碼向訊息推播伺服器登錄regId,例如
         * register(context, regId);
         * */       
        GCMRegistrar.setRegisteredOnServer(context, true);
  }

(3). 向GCM Server註銷裝置後,GCMBroadcastReceiver會調用onUnregistered(),在此須同步向訊息推播伺服器取消登錄裝置的registration Id。

  @Override
  protected void onUnregistered(Context context, String regId) {
        /**
         * 在此應撰寫程式碼向訊息推播伺服器取消登錄regId,例如
         * unregister(context, regId);
         * */       
        GCMRegistrar.setRegisteredOnServer(context, false);
  }

(4). 收到GCM Server送來的推播訊息時,GCMBroadcastReceiver會調用onMessage(),在此透過Notification通知用戶。

  @Override
  protected void onMessage(Context context, Intent intent) {
     //取出訊息payload內容
     String contentTitle = intent.getStringExtra("contentTitle");  
     String contentText = intent.getStringExtra("contentText");
    //在裝置狀態列顯示Notification通知用戶
     generateNotification(context, contentTitle, contentText); 
    }
  private static void generateNotification(Context context,
     String contentTitle, String contentText) {
     NotificationManager notificationManager = (NotificationManager)
          context.getSystemService(Context.NOTIFICATION_SERVICE);
     Notification notification = new Notification(
       R.drawable.ic_launcher,
       contentTitle,
       System.currentTimeMillis());
     //設定notification要喚醒的Activity      
     Intent notificationIntent = new Intent(context, MainActivity.class);
     notificationIntent.setFlags(
       Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_SINGLE_TOP);
     PendingIntent intent = PendingIntent.getActivity(
       context,
       0,
       notificationIntent,
       PendingIntent.FLAG_UPDATE_CURRENT);
     //設定notification內容
     notification.setLatestEventInfo(context, contentTitle, contentText, intent);
     //自動移除看過的notification
     notification.flags |= Notification.FLAG_AUTO_CANCEL;
     //發送notification
     notificationManager.notify( 0, notification);     
  }

最後是撰寫MainActivity類別程式碼,在onCreate()方法中進行以下作業:
  protected void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
     setContentView(R.layout.activity_main);
     //檢查裝置是否支援GCM
     GCMRegistrar.checkDevice(this);
     //檢查應用程式之AndroidMainfest.xml設定是否正確
     GCMRegistrar.checkManifest(this);
     //取得registration id
     final String regId = GCMRegistrar.getRegistrationId(this);
     if (regId.equals("")) {        //尚未註冊
       //GCM server註冊以取得registration id
       GCMRegistrar.register(this, "Your_Sender_ID");
     }
  }

2013年2月8日 星期五

使用GCM服務(五) 設計GCM應用程式(1)

1. 建立GCM Client專案,注意!GCM只適用Android 2.2以上版本。
2. 將GCM library(android sdk目錄下之\extras\google\gcm\gcm-client\dist\gcm.jar檔)複製到GCM Client專案的libs目錄下。
3. 開啟AndroidManifest.xml檔,加入以下宣告(如果是Android 4.1以上版本專案,則不需要這個步驟),其中my_app_package必須替換為專案套件名稱。

  <permission android:name="my_app_package.permission.C2D_MESSAGE"
     android:protectionLevel="signature" />
  <uses-permission
     android:name="my_app_package.permission.C2D_MESSAGE" />

4. 在AndroidManifest.xml檔中加入以下使用權限宣告。

  <uses-permission
     android:name="com.google.android.c2dm.permission.RECEIVE" />
  <uses-permission android:name="android.permission.INTERNET" />
  <uses-permission android:name="android.permission.GET_ACCOUNTS" />
  <uses-permission android:name="android.permission.WAKE_LOCK" />

5. 在AndroidManifest.xml之內宣告GCM receiver(由GCM library提供),負責處理由GCM system framework送出的com.google.android.c2dm.intent.RECEIVE以及com.google.android.c2dm.intent.REGISTRATION二種intent作業。
其中<category>的name屬性值(my_app_package)必須替換為專案套件名稱,但如果是Android 4.1以上版本專案,則不需要宣告<category>標籤。

  <receiver
     android:name="com.google.android.gcm.GCMBroadcastReceiver"
     android:permission="com.google.android.c2dm.permission.SEND" >
     <intent-filter>
       <action android:name="com.google.android.c2dm.intent.RECEIVE" />
       <action android:name="com.google.android.c2dm.intent.REGISTRATION" />
       <category android:name="my_app_package" />
     </intent-filter>
  </receiver>

6. 在AndroidManifest.xml之內加入以下的intent service宣告:
  <service android:name=".GCMIntentService" />
在此的name屬性值為繼承自com.google.android.gcm.GCMBaseIntentService的自訂Service類別名稱,當GCMBroadcastReceiver收到推播訊息時就會調用這個intent service。

7. 建立GCMIntentService類別框架

public class GCMIntentService extends GCMBaseIntentService {
  public GCMIntentService() {
     // TODO Auto-generated constructor stub
  }
  public GCMIntentService(String... senderIds) {
     super(senderIds);
     // TODO Auto-generated constructor stub
  }
  @Override
  protected void onError(Context arg0, String arg1) {
     // TODO Auto-generated method stub
  }
  @Override
  protected void onMessage(Context arg0, Intent arg1) {
     // TODO Auto-generated method stub
  }
  @Override
  protected void onRegistered(Context arg0, String arg1) {
     // TODO Auto-generated method stub
  }
  @Override
  protected void onUnregistered(Context arg0, String arg1) {
     // TODO Auto-generated method stub
  }
}

2013年2月3日 星期日

使用GCM服務(四) 訊息推播伺服器(2)

Plain text的POST請求封包由於只支援單點推播,HTTP body內必須改用registration_id,而data欄位值須改為data.<key>=value,例如:data.title=Android Apps初學必修課&data.isbn=978-986-276-704-7&registration_id=reg_id。另外,中文字編碼時可能與「&」符號衝突,因此最好使用urlencode()函式處理。
以下PHP程式碼使用plain text格式送出GCM請求封包。
  define("GOOGLE_API_KEY", "your_api_key");
  $reg_id = 'device_reg_id';
  //payload data
  $payload = 'data.contentTitle='.urlencode('耕雲智慧').
'&data.contentText='.urlencode('
測試訊息推播');
  //http header
  $headers = array('Authorization: key=' . GOOGLE_API_KEY,
'Content-Type:application/x-www-form-urlencoded;charset=UTF-8');
  $fields = $payload.'&registration_id='.$reg_id;
  //curl connection
  $ch = curl_init();
   curl_setopt($ch, CURLOPT_URL, 'https://android.googleapis.com/gcm/send');
  curl_setopt($ch, CURLOPT_POST, true);
  curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true );
  curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
  curl_setopt($ch, CURLOPT_POSTFIELDS, $fields);
  $result = curl_exec($ch);
   curl_close($ch);
  echo $result;
?>