相信如果你做的手机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);
}