相信如果你做的手機app需要給國外的使用者使用的話,你就不能使用國内的百度推送、信鴿推送等等的免費推送服務,需要使用android 自帶的google最新的gcm推送機制,但因為谷歌服務需要連接配接vpn使用,而且國内大部分的手機都是将内置的谷歌服務架構閹割掉了,是以對開發人員來說無論是測試還是開發都會遇到不小的阻礙,下面就一個個的去解決:
1.首先需要具有谷歌服務架構的手機,(也可以使用模拟器推薦bluestacks,非常好用),真機需要先root之後,然後下載下傳谷歌服務安裝程式的軟體,自動安裝即可。準備一個谷歌賬号,前提是你可以連接配接vpn,然後将手機添加一個谷歌郵箱賬号。
2.注冊一個開發者賬号,需要money,拿到一個程式的唯一識别碼key,關于如何注冊,以及如何将谷歌賬号添加gcm推送服務,我的這篇博文已經講得很詳細了,傳送門:
android google 開發者賬号gcm 有非常詳細的解釋,有問題可以參考。
3.看過我的第二個步驟之後,相信你已經在你的手機app程式和伺服器上面添加了谷歌的gcm服務,也可以發送消息了,那麼真的恭喜你,這一步很不容易。不過你會發現一個小問題:當你發送多條通知的時候,總會顯示一條通知,那是因為你接收通知的函數,預設的id号都是0,你需要将id設定為唯一的,谷歌官方提供的是使用目前的時間作為唯一辨別符,這樣就可以區分每條通知,在通知欄上同時顯示多條了,如下代碼:
/**
* Issues a notification to inform the user that server has sent a message.
*/
@SuppressWarnings("deprecation")
private static void generateNotification(Context context, String message) {
int icon = R.drawable.ic_launcher;
<span style="color:#ff0000;">long when = System.currentTimeMillis();</span>
NotificationManager notificationManager = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = new Notification(icon, message, when);
String title = context.getString(R.string.app_name);
Intent notificationIntent = new Intent(Intent.ACTION_MAIN);
notificationIntent.addCategory(Intent.CATEGORY_LAUNCHER);
notificationIntent.setClass(context, LoginActivity.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
PendingIntent intent = PendingIntent.getActivity(context, 0,
notificationIntent, 0);
notification.setLatestEventInfo(context, title, message, intent);
notification.flags |= Notification.FLAG_AUTO_CANCEL;
<span style="color:#ff0000;">int idtify = (int) when;
notificationManager.notify(idtify, notification);</span>
}
4.當你很慶幸自己已經可以收到谷歌的通知了,可是測試人員會抱怨,為什麼有時候能及時的收到通知,大部分時候就根本就收不到通知了呢。這個問題參考我的另一個博文的解釋: android gcm推送延遲 主要延遲或者沒有推送的原因是因為谷歌保持的長連接配接被服務商無情的斷掉了,當你發送的時候,就根本沒有發送給谷歌官方,也就導緻你無法接收到消息或者有延遲,解決的方式是每個5秒,通知谷歌,保持長連接配接,使用alarmanager每隔5秒執行如下兩行代碼即可,就可以成功解決:
UploadPOIService.this.sendBroadcast(new Intent(
"com.google.android.intent.action.GTALK_HEARTBEAT"));
UploadPOIService.this.sendBroadcast(new Intent(
"com.google.android.intent.action.MCS_HEARTBEAT"));
部分主要的程式如下:
a.添加向谷歌注冊id,以及每隔幾秒發送心跳連接配接:
import client.verbank.mtp.allone.doc.DocCaptain;
import client.verbank.mtp.allone.frame.MainActivity;
import client.verbank.mtp.allone.frame.account.MultipleAccountActivity;
import client.verbank.mtp.allone.util.SharedPreferencesUtil;
import client.verbank.mtp.allone.util.StringUtil;
import client.verbank.mtp.allone.util.gcm.ServerUtilities;
import client.verbank.mtp.allone.util.gcm.ServiceUtil;
import com.google.android.gcm.GCMRegistrar;
/**
*
* login
*
* @author wangyubo
*
*/
public class LoginActivity extends ApplicationActivity {
private static final String TAG = "GCMIntentService";
@Override
protected void onCreate(Bundle saveInstanceState) {
super.onCreate(saveInstanceState);
*/
// // 注冊谷歌消息
try {
GoogleGcm();
// 每個5秒發送心跳,保持長連接配接
ServiceUtil.invokeTimerPOIService(this);
} catch (Exception ex) {
ex.printStackTrace();
}
}
private void GoogleGcm() {
checkNotNull(SERVER_URL, "SERVER_URL");
checkNotNull(SENDER_ID, "SENDER_ID");
GCMRegistrar.checkDevice(this);
GCMRegistrar.checkManifest(this);
registerReceiver(mHandleMessageReceiver, new IntentFilter(
DISPLAY_MESSAGE_ACTION));
regId = GCMRegistrar.getRegistrationId(this);
DocCaptain.getInstance().setREGID(regId);
Toast.makeText(LoginActivity.this,
"手機注冊成功,id号為" + regId + "=============", Toast.LENGTH_LONG)
.show();
System.out.println("手機已經成功注冊完成,拿到的谷歌注冊ID号為" + regId);
LoginActivity.this.sendBroadcast(new Intent(
"com.google.android.intent.action.GTALK_HEARTBEAT"));
LoginActivity.this.sendBroadcast(new Intent(
"com.google.android.intent.action.MCS_HEARTBEAT"));
if (regId.equals("")) {
GCMRegistrar.register(this, SENDER_ID);
} else {
if (GCMRegistrar.isRegisteredOnServer(this)) {
System.out.println("手機已經向谷歌注冊成功");
} else {
final Context context = this;
mRegisterTask = new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
boolean registered = ServerUtilities.register(context,
regId);
if (!registered) {
// GCMRegistrar.unregister(context);
}
return null;
}
@Override
protected void onPostExecute(Void result) {
mRegisterTask = null;
}
};
mRegisterTask.execute(null, null, null);
}
}
}
@Override
public void onDestroy() {
if (mRegisterTask != null) {
mRegisterTask.cancel(true);
}
// unregisterReceiver(mHandleMessageReceiver);
// GCMRegistrar.onDestroy(this);
super.onDestroy();
}
private void checkNotNull(Object reference, String name) {
if (reference == null) {
throw new NullPointerException(getString(R.string.error_config,
name));
}
}
private final BroadcastReceiver mHandleMessageReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String newMessage = intent.getExtras().getString(EXTRA_MESSAGE);
System.out.println(newMessage + "\n");
// mDisplay.append();
}
};
}
}
}
public static void invokeTimerPOIService(Context context) {
PendingIntent alarmSender = null;
Intent startIntent = new Intent(context, UploadPOIService.class);
startIntent.setAction(Constants.POI_SERVICE_ACTION);
try {
alarmSender = PendingIntent.getService(context, 0, startIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
} catch (Exception e) {
Log.i("ServiceUtil-AlarmManager", "failed to start " + e.toString());
}
AlarmManager am = (AlarmManager) context
.getSystemService(Activity.ALARM_SERVICE);
am.setInexactRepeating(AlarmManager.RTC_WAKEUP,
System.currentTimeMillis(), Constants.ELAPSED_TIME, alarmSender);
}
代碼太多,上傳一些檔案好了:如下連結:http://download.csdn.net/detail/omayyouhappy/9395645