以
http://blog.sina.com.cn/s/blog_62f189570101bw5x.html
的基础上进行修改完善的。
由于项目的需求,需要将推送做到客户端。用的引擎是cocos2dx的。但是我看了下,大概思路还是安卓普遍都可以使用的。
大致思路就是建立一个service,然后在service中不断的去判断当前时间是否达到了指定时间,打到了指定时间就用安卓的notification进行推送。
首先在c++中定义一个Notification的管理类:
#ifndef __CCNOTIFICATIONMANAGER_H__
#define __CCNOTIFICATIONMANAGER_H__
#define NM CCNotificationManager::getNotificationManager()
#include "GlobalHead.h"
class CCNotificationManager
{
public:
static CCNotificationManager* getNotificationManager();
void notification(const char * message, int delay, int repeats, const char * key);
private:
CCNotificationManager();
private:
static CCNotificationManager* m_pNotifiMgr;
};
#endif
void notification(const char * message, int delay, int repeats, const char * key); 的作用就是将需要的类容,时间等 发送到java那边进行存储。
key 这个字段可以不管,这是ios需要使用的,现在暂时不需要管。(我是在上面那个地址的内容上进行修改的,也可以单独区分ios 和 安卓的)
#include "CCNotificationManager.h"
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
#include "CCNotificationHelper.h"
#elif (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
#include "CCNotificationAndroid.h"
#endif
CCNotificationManager* CCNotificationManager::m_pNotifiMgr = NULL;
#include "..\Player\FmLocalPlayer.h"
CCNotificationManager::CCNotificationManager()
{
}
CCNotificationManager* CCNotificationManager::getNotificationManager()
{
if (NULL == m_pNotifiMgr)
{
m_pNotifiMgr = new CCNotificationManager();
return m_pNotifiMgr;
}
return m_pNotifiMgr;
}
void CCNotificationManager::notification(const char * message, int delay, int repeats, const char * key)
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
// CNH->pushMessage(message ,delay ,repeats,key );
CNH->pushMessage(message, delay, 0, key);
#elif (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
long time = GetLocalPlayer()->getCurrentTime();
java_push(message, delay, repeats);
#endif
}
iso的展示不需要去看。
时间的获取是这样的:
long Player::getCurrentTime()
{
struct tm * tm ;
time_t timep;
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
time(&timep);
#else
struct cc_timeval now;
CCTime::gettimeofdayCocos2d(&now, NULL);
timep = now.tv_sec;
#endif
tm = localtime(&timep);
long timeSecond = tm->tm_sec + tm->tm_min * 60 + tm->tm_hour * 3600;
return timeSecond;
}
然后看java_push
#ifndef __CCNOTIFICATION_ANDROID_H__
#define __CCNOTIFICATION_ANDROID_H__
#include "SDK/GlobalHead.h"
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
#include <jni.h>
extern"C"
{
extern void java_push(const char *src,int time,int rep);
extern void java_removePush();
}
#endif
#endif
#include "CCNotificationAndroid.h"
#include "Common.h"
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
#include "jni/JniHelper.h"
#include <android/log.h>
#include <jni.h>
extern"C"
{
void java_push(const char *src,int delaytime,int rep)
{
JniMethodInfo t;
//LI
bool ishave = false;
ishave = JniHelper::getStaticMethodInfo(t, "org/cocos2dx/bighero/BigHero", "pushMessage", "(Ljava/lang/String;II)V");
if (ishave)
{
jstring messageStr = t.env->NewStringUTF(src);
t.env->CallStaticVoidMethod(t.classID, t.methodID, messageStr,delaytime,rep);
t.env->DeleteLocalRef(messageStr);
}
}
void java_removePush()
{
JniMethodInfo minfo;
bool isHave = JniHelper::getStaticMethodInfo(minfo, "org/cocos2dx/bighero/BigHero", "removeNotification", "()V");
if (!isHave)
{
CCLOG("jni:此函数不存在");
}
else
{
minfo.env->CallStaticVoidMethod(minfo.classID, minfo.methodID);
}
}
}
#endif
这里,本来是想着用直接把long类型的时间用jni传递到java里面直接使用,但是这样的话,前面的获取时间的方法需要修改下。我这里的方法是直接传入delay的时间。(原谅我对Jni 和java 不熟悉)
然后是java 部分:
在主activity中实现:
public static void pushMessage(String message,int time,int repeats) {
// System.out.println("alpaca.passFromJni()"+mark);
NotificationMessage nmObj = new NotificationMessage();
String [] ss = message.split("#");
nmObj.setMessage(ss[0]);
nmObj.setTitle(ss[1]);
long curtime = System.currentTimeMillis();
nmObj.setMark(curtime + time * convert);
nmObj.setId(repeats);
BigHero.SerializeMethod(nmObj);
}
我这里的message 传入的是安卓Notification 需要用到的title 和 info,我用title#info 传入。
public static void SerializeMethod(NotificationMessage message) {
Intent intent = new Intent();
intent.setClass(bighero, NotifitionService.class);
Bundle mBundle = new Bundle();
mBundle.putSerializable(SER_KEY, message);
intent.putExtras(mBundle);
//
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
bighero.startService(intent);
}
这里就是开启我们的推送服务
存储数据的类:
public class NotificationMessage implements Serializable {
private static final long serialVersionUID = -7060210544600464481L;
private String message;
private long mark;
private int id;
private String title;
public String getMessage() {
return message;
}
public String getTitle() {
return title;
}
public void setTitle(String title){
this.title = title;
}
public void setMessage(String message) {
this.message = message;
}
public long getMark() {
return mark;
}
public void setMark(long mark) {
this.mark = mark;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public NotificationMessage(String message, long mark, int id) {
super();
this.message = message;
this.mark = mark;
this.id = id;
}
public NotificationMessage() {
}
}
然后看推送的service
public class NotifitionService extends Service {
static List<NotificationMessage> mMessageList = new ArrayList<NotificationMessage>();
String mMessage = "";
String mTitle = "";
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId)
{
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
Timer timer = new Timer(true);
timer.schedule(new java.util.TimerTask(){
@Override
public void run() {
// TODO Auto-generated method stub
if (checkPauseState()) {
if(!isAppOnForeground())
showNotification();
}
}
},0,1 * 1000);
}
@Override
public void onStart(Intent intent, int startId) {
// TODO Auto-generated method stub
super.onStart(intent, startId);
if (intent != null) {
NotificationMessage notimessage = (NotificationMessage) intent.getSerializableExtra(BigHero.SER_KEY);
long time = notimessage.getMark();
mMessageList.add(notimessage);
}
}
public boolean checkPauseState()
{
long curtime = System.currentTimeMillis();
System.out.println("NotifitionService=========="+curtime);
if (mMessageList.size() > 0) {
int listsize = mMessageList.size();
for (int i = 0; i < listsize; i++) {
if (mMessageList.get(i).getMark() < curtime + 1 *1000 && mMessageList.get(i).getMark() > curtime - 1 * 1000) {
mMessage = mMessageList.get(i).getMessage();
mTitle = mMessageList.get(i).getTitle();
mMessageList.remove(i);
return true;
}
}
return false;
}
else
{
return false;
}
}
public void showNotification(){
Notification notification = new Notification();
notification.icon = R.drawable.ic_launcher;
notification.tickerText = mMessage;
notification.when = System.currentTimeMillis();
notification.defaults = Notification.DEFAULT_SOUND;
notification.flags |= Notification.FLAG_AUTO_CANCEL;
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setClassName(this,"org.cocos2dx.bighero.BigHero");
intent.addCategory(Intent.CATEGORY_LAUNCHER);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
PendingIntent pintent = PendingIntent.getActivity(NotifitionService.this, 0,intent,0);
notification.setLatestEventInfo(NotifitionService.this,mTitle,mMessage,pintent);
String service = Context.NOTIFICATION_SERVICE;
NotificationManager mNotificationManager =(NotificationManager)getSystemService(service);
mNotificationManager.notify(R.string.app_name, notification);
}
public class PushThread implements Runnable
{
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println("CCNotifitionService.PushThread.run()"+mMessageList.size());
while (true) {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
// TODO: handle exception
e.printStackTrace();
}
if (checkPauseState()) {
if(!isAppOnForeground())
showNotification();
}
}
}
}
/**
* 程序是否在前台运行
*
* @return
*/
public boolean isAppOnForeground() {
// Returns a list of application processes that are running on the
// device
ActivityManager activityManager = (ActivityManager) getApplicationContext().getSystemService(Context.ACTIVITY_SERVICE);
String packageName = getApplicationContext().getPackageName();
List<RunningAppProcessInfo> appProcesses = activityManager
.getRunningAppProcesses();
if (appProcesses == null)
return false;
for (RunningAppProcessInfo appProcess : appProcesses) {
// The name of the process that this object is associated with.
if (appProcess.processName.equals(packageName)
&& appProcess.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
return true;
}
}
return false;
}
}
更多的可以去看看Notification的实现
最后是AndroidManifest 中添加服务
<service android:name="NotifitionService"
android:process=":system" >
</service>
请注意,这里的提升进程的级别是:system 而不是system ,网上一堆的system 把我害惨了。。。。。