這篇要來介紹的是 如何使用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