這篇要來介紹的是 如何使用GCM推播服務,我們要完成上圖,按下按鈕註冊Token,按下發送,Push一則推播給自己的裝置,在Coding之前有幾件事情要先做:
●到你的Google Api主控台
●建立一個新專案
●開啟Cloud Messaging for Android Api服務
●新增伺服器憑證
●取得Sender ID 與 伺服器Api Key
(藍字部份是因為這個Demo要發送Push給自己,若只想單純接收而已可以忽略)
下面會有圖文介紹,若還有疑問可以來看官方說明
建立一個新專案
點選首頁 -> 記下Sender ID
點選API -> 找到Cloud Messaging for Android -> 進入設定為啟動
點選憑證 -> 新增憑證 -> Api金鑰 -> 伺服器金鑰 -> 不用輸入東西直接建立
記下Api Key
Demo專案介紹:
MainActivity(主畫面)
GcmService(接收Push的背景服務)
RegisterTask(註冊Token的非同步任務)
SendPushTask(發送Push的非同步任務)
activity_main(主畫面Layout)
打開你的gradle,引用Lib
compile 'com.google.android.gms:play-services:7.5.0'
activity_main這個layout很簡單,就不再做介紹了
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="10dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="我的 Token :"
/>
<TextView
android:textColor="#FF0000"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="空"
android:id="@+id/tokenTv"
/>
</LinearLayout>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="註冊 TOKEN"
android:id="@+id/registerBtn"
/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="10dp">
<EditText
android:id="@+id/messageEt"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:hint="這裡輸入要發給自己的內容"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="發送"
android:id="@+id/sendPushBtn"
/>
</LinearLayout>
</LinearLayout>
先來看MainActivity
15.16列 請記得改成剛剛第一步記下來的Sender ID與Api Key
52.53列 JSONObject 的 key 是GCM api的固定格式,不能改唷!
package com.anson.pushtest;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
public class MainActivity extends Activity {
public static final String GCM_SENDER_ID = "你的Sender ID";
public static final String SERVER_API_KEY = "你的 Api Key";
public static final String TEST_MY_MESSAGE_KEY = "MY_PUSH_MESSAGE";
private TextView mTokenTv;
private Button mRegisterBtn , mSendPushBtn;
private EditText mMessageEt;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTokenTv = (TextView)findViewById(R.id.tokenTv);
mRegisterBtn = (Button)findViewById(R.id.registerBtn);
mSendPushBtn = (Button)findViewById(R.id.sendPushBtn);
mMessageEt = (EditText)findViewById(R.id.messageEt);
mRegisterBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new RegisterTask(MainActivity.this,mTokenTv).execute();
}
});
mSendPushBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String targetToken = mTokenTv.getText().toString();
String message = mMessageEt.getText().toString();
new SendPushTask(MainActivity.this).execute(getPushMessage(targetToken,message));
}
});
}
/**
* 取得推波訊息格式
*/
private static String getPushMessage(String targetToken,String message) {
String KEY_REGISTRATION_IDS = "registration_ids";
String KEY_DATA = "data";
JSONObject jObj = new JSONObject();
JSONArray idsArray = new JSONArray();
idsArray.put(targetToken);
JSONObject jObjData = new JSONObject();
try {
jObjData.put(TEST_MY_MESSAGE_KEY,message);
jObj.put(KEY_REGISTRATION_IDS, idsArray);
jObj.put(KEY_DATA, jObjData);
} catch (JSONException e) {
e.printStackTrace();
}
return jObj.toString();
}
}
註冊任務 RegisterTask
package com.anson.pushtest;
import android.app.ProgressDialog;
import android.content.Context;
import android.os.AsyncTask;
import android.widget.TextView;
import android.widget.Toast;
import com.google.android.gms.gcm.GoogleCloudMessaging;
/**
* Created by Anson on 2015/8/22.
*/
public class RegisterTask extends AsyncTask<Void, Void, String> {
private ProgressDialog mDialog;
private Context mContext;
private TextView mTokenTv;
public RegisterTask(Context context,TextView tokenTv) {
mDialog = new ProgressDialog(context);
mDialog.setTitle("提示");
mDialog.setMessage("註冊Token中~~~~");
mDialog.setCancelable(false);
mContext = context;
mTokenTv = tokenTv;
}
@Override
protected void onPreExecute() {
mDialog.show();
super.onPreExecute();
}
@Override
protected String doInBackground(Void... params) {
String token = null;
try {
token = GoogleCloudMessaging.getInstance(mContext).register(MainActivity.GCM_SENDER_ID);
} catch (Exception e) {
e.printStackTrace();
}
return token;
}
@Override
protected void onPostExecute(String token) {
if (token == null) {
//註冊token失敗
Toast.makeText(mContext,"註冊失敗,請檢查你的 SENDER_ID 是否有設定正確",Toast.LENGTH_LONG).show();
}else {
mTokenTv.setText(token);
}
mDialog.cancel();
super.onPostExecute(token);
}
}
發送任務 SendPushTask
package com.anson.pushtest;
import android.app.ProgressDialog;
import android.content.Context;
import android.os.AsyncTask;
import android.widget.Toast;
import java.io.BufferedWriter;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
/**
* Created by Anson on 2015/8/22.
*/
public class SendPushTask extends AsyncTask<String, Void, Integer> {
private ProgressDialog mDialog;
private Context mContext;
public SendPushTask(Context context) {
mDialog = new ProgressDialog(context);
mDialog.setTitle("提示");
mDialog.setMessage("發送Push中~~");
mDialog.setCancelable(false);
mContext = context;
}
@Override
protected void onPreExecute() {
mDialog.show();
super.onPreExecute();
}
@Override
protected Integer doInBackground(String... params) {
int statusCode = -1;
try {
URL url = new URL("https://android.googleapis.com/gcm/send");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(10000);
conn.setConnectTimeout(10000);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/json");
conn.setRequestProperty("Authorization", "key = "+ MainActivity.SERVER_API_KEY);
conn.setDoInput(true);
conn.setDoOutput(true);
OutputStream os = conn.getOutputStream();
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os, "UTF-8"));
writer.write(params[0]);
writer.flush();
writer.close();
os.close();
conn.connect();
statusCode = conn.getResponseCode();
} catch (Exception e) {
e.printStackTrace();
}
return statusCode;
}
@Override
protected void onPostExecute(Integer statusCode) {
if(statusCode!=200){
Toast.makeText(mContext,"發送失敗,請檢查你的 SERVER_API_KEY 是否有設定正確",Toast.LENGTH_LONG).show();
}
mDialog.cancel();
super.onPostExecute(statusCode);
}
}
推播訊息監聽服務 GcmService
package com.anson.pushtest;
import android.os.Bundle;
import com.google.android.gms.gcm.GcmListenerService;
/**
* Created by Anson on 2015/8/22.
*/
public class GcmService extends GcmListenerService{
@Override
public void onMessageReceived(String from, Bundle data) {
String message = data.getString(MainActivity.TEST_MY_MESSAGE_KEY);
System.out.println("收到推播了-from:" + from);
System.out.println("收到推播了-data:" + message);
}
}
這邊要特別注意一下,裡面的所有package name都要記得改成你的
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="[你的package_name]" >
<!-- 網路權限 -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- 休眠喚醒權限 -->
<uses-permission android:name="android.permission.WAKE_LOCK" />
<!-- 推播權限 -->
<permission
android:name="[你的package_name].permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="[你的package_name].permission.C2D_MESSAGE" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
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.gms.gcm.GcmReceiver"
android:exported="true"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="[你的package_name]" />
</intent-filter>
</receiver>
<service
android:name=".GcmService"
android:exported="false" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</service>
</application>
</manifest>
1.先按註冊Token
2.完成後會看到紅字部分改變了
3.這時就可以發送訊息給自己囉!
1. GCM 僅提供上限 4kb 的輕量資料傳遞
2. 註冊完的Token 時間久了是有可能改變(失效)的,但我目前使用起來還沒有出現這個問題
3. 若App在尚未刪除狀態下,重新註冊Token,有有可能會是一組不同的 Token,但也有可能一樣
4. 若App在刪除後重新安裝,重新註冊Token,這時會是一組新的 Token
都看到最後了,代表你還蠻有上進心的XD