注:中國大陸體驗不好,不建議在中國大陸使用
1.創建Google API項目:
登陸Google控制檯:https://code.google.com/apis/console/,如果你還沒創建過項目,頁面會提示:
如果您已經有項目,你看到的第一頁將是儀表板頁面。從那裏你可以通過打開項目的下拉菜單(左上角),並選擇Other>Create一個新的項目。
注:創建項目是提示要輸入第三方服務器ip,可以不輸入直接創建。
創建完了之後要記住上面的Project ID,也就是下面代碼中要使用到的SENDER_ID。
2.開啓GCM服務:
在谷歌API的控制頁面的主頁中,選擇Services。
在右側找到:Google Cloud Messaging forAndroid, 設置按鈕的狀態值爲ON。
在服務條款頁面中接受這些條款。
3.獲得Server API密鑰(服務器或者測試的時候要用到):
在谷歌API的控制頁面的主頁中,選擇API Access。選擇Create new Server key,記住API key。
4.安裝GCM庫:
打開SDK Manager,如果你的SDK Manager在Revision 20以下請下載更新後在安裝GCM庫。安裝 Extras > Google Cloud Messaging for Android Library,如果沒看到這一選項,下方的show中有一個爲"Obsolete"的CheckBox,勾選上即有。它會創建一個YOUR_SDK_ROOT/extras/google/ 文件夾。
5.寫客服端代碼
注:運行着需要使用GCM的android程序的手機. 這必須是一個2.2的Android設備,安裝Google Play Store, 如果設備運行Android版本低於4.0.4它必須至少有一個登錄谷歌賬戶。或者運行具有谷歌api 的Android 2.2虛擬機。
前提:從 YOUR_SDK_ROOT/extras/google/gcm/gcm-client/dist/中拷貝gcm.jar到你的項目下面,另外,android模擬器必須擁有Google Apis,如在創建模擬器時Target選中帶有Google APIs(Google Inc.)字眼的。
AndroidManifest.xml(注意拼寫的正確性以及順序)
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.huangri.sendmsg.gcmclient" >
<!-- GCM僅支持Android 2.2及以上 -->
<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="20" />
<!-- 自定義權限,你的默認包.permission.C2D_MESSAGE,我這裏是com.huangri.sendmsg.gcmclient -->
<permission android:name="com.huangri.sendmsg.gcmclient.permission.C2D_MESSAGE" android:protectionLevel="signature" />
<uses-permission android:name="com.huangri.sendmsg.gcmclient.permission.C2D_MESSAGE" />
<!-- 注意下面的順序,否則可能導致獲取不到客服端的註冊ID -->
<!-- GCM connects to Google Services. -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- GCM requires a Google account. -->
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<!-- Keeps the processor from sleeping when a message is received. -->
<uses-permission android:name="android.permission.WAKE_LOCK" />
<!-- App receives GCM messages. -->
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".GcmClientActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- 註冊一個廣播接收器,用於接收服務器發出的廣播,不用用代碼實現 -->
<receiver
android:name="com.google.android.gcm.GCMBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<!-- Receives the actual messages. -->
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<!-- Receives the registration id. -->
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<!-- 你的默認包名,我這裏是com.huangri.sengmsg.gcmclient -->
<category android:name="com.huangri.sendmsg.gcmclient" />
</intent-filter>
</receiver>
<!-- 廣播接收器默認調用的service -->
<service android:name=".GCMIntentService" />
</application>
</manifest>
GCMIntentService.java(名字不可改動,否則會獲取不到設備註冊ID,並且要繼承GCMBaseIntentService)
package com.huangri.sendmsg.gcmclient;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.widget.Toast;
import com.google.android.gcm.GCMBaseIntentService;
import com.google.android.gcm.GCMRegistrar;
/**
* Created by HUANGRI on 11/27/2014.
*/
public class GCMIntentService extends GCMBaseIntentService {
private final String TAG = "GCMIntentService";
public static final String SENDER_ID = "314810456832";
//SENDER_ID就是上面說到的Project ID
public GCMIntentService() {
super(SENDER_ID);
}
//當設備試圖註冊或註銷時,但是GCM服務器無效時。GCM庫會使用應急方案重試操作,除非這個方式被重寫並返回false。
//這個方法是可選的並且只有當你想顯示信息給用戶或想取消重試操作的時候纔會被重寫。
@Override
protected boolean onRecoverableError(Context context, String errorId) {
return super.onRecoverableError(context, errorId);
}
//當你的服務器發送了一個消息到GCM後會被調用,並且GCM會把這個消息傳送到相應的設備。
//如果這個消息包含有效負載數據,它們的內容會作爲Intent的extras被傳送。
@Override
protected void onMessage(Context context, Intent intent) {
Log.e(TAG, "messageFrom = " + intent.getStringExtra("messageFrom"));
Log.e(TAG, "message = " + intent.getStringExtra("msg"));
final String info = intent.getStringExtra("msg");
NotificationManager notificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = new Notification(R.drawable.ic_launcher, "Notification", System.currentTimeMillis());
Intent intent_action = new Intent(context, GcmClientActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent_action, 0);
notification.setLatestEventInfo(context, "GCM Message", "You have a message!: " + info, pendingIntent);
notification.flags = Notification.FLAG_AUTO_CANCEL;
notification.defaults = Notification.DEFAULT_SOUND;
notificationManager.notify(0, notification);
}
//當設備試圖註冊或註銷時,但是GCM返回錯誤時此方法會被調用。通常此方法就是分析錯誤並修復問題而不會做別的事情。
@Override
protected void onError(Context context, String s) {
Log.e(TAG, "onError():error occurred");
}
//收到註冊Intent後此方法會被調用,GCM分配的註冊ID會做爲參數傳遞到設備/應用程序對。
//通常,你應該發送regid到你的服務器,這樣服務器就可以根據這個regid發消息到設備上。
@Override
protected void onRegistered(Context context, String s) {
Log.e(TAG, "onRegistered():registered already");
}
//當設備從GCM註銷時會被調用。通常你應該發送regid到服務器,這樣就可以註銷這個設備了。
@Override
protected void onUnregistered(Context context, String s) {
Log.e(TAG, "onUnregistered():unregister occurred");
}
}
GcmClientActivity.java
package com.huangri.sendmsg.gcmclient;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import com.google.android.gcm.GCMRegistrar;
public class GcmClientActivity extends ActionBarActivity {
private final String TAG = "GcmClientActivity";
private TextView message_content;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_gcm_client);
message_content = (TextView)findViewById(R.id.message_receiver);
//檢查設備和AndroidManifest是否支持GCM
GCMRegistrar.checkDevice(this);
GCMRegistrar.checkManifest(this);
//啓動前先獲得設備ID,判斷設備是否註冊過
final String regId = GCMRegistrar.getRegistrationId(this);
if ("".equals(regId)) {
//註冊register(Context context, String SENDER_ID)
GCMRegistrar.register(this, GCMIntentService.SENDER_ID);
Log.i(TAG, "First registered,isRegistered = " + GCMRegistrar.isRegistered(this) + ", ID = " + GCMRegistrar.getRegistrationId(this));
message_content.setText("First registered,isRegistered = " + GCMRegistrar.isRegistered(this) + ", ID = " + GCMRegistrar.getRegistrationId(this));
} else {
GCMRegistrar.setRegisteredOnServer(this, true);
Log.i(TAG, "Already registered!");
Log.i(TAG, "registerID = " + GCMRegistrar.getRegistrationId(this));
message_content.setText("Already registered!\n" + "registerID = " + GCMRegistrar.getRegistrationId(this));
}
Button btn_unregister = (Button)findViewById(R.id.unregister);
btn_unregister.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//向服務器註銷設備ID
GCMRegistrar.unregister(getBaseContext());
message_content.setText("unregister");
}
});
//下面的是ActionBar的方法,與本文無關
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.gcm_client, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
6.測試:
這裏就不寫服務器代碼,自己網上早去,測試可以使用ChromePoster插件(安裝步驟:打開谷歌瀏覽器==>工具==>擴展程序==>查找ChromePoster插件並安裝)
點擊右側的P按鈕,
分別輸入:
URL: https://android.googleapis.com/gcm/send
Header:
Name:
Authorization Value: key=你的API
key 點擊Add/Change
Name:Content-Type Value: application/json forJSON; application/x-www-form-urlencoded;charset=UTF-8for plain text 點擊Add/Change
Content
Body:
{ "data": {
/////////這裏爲發送的消息,以鍵值方式傳送,填入時去掉這一行//////////
"鍵": "值"
},
"registration_ids": ["你的設備的註冊ID"]
}
最後點擊POST就可以看到測試結果了。