极光消息推送服务器端开发实现推送(下)
前面我们已经实现了通过我们自己的服务器生成消息向极光消息推送服务器发送推送消息的功能,下面我们来看看如何在手机客户端实现消息接收。
一、在极光上建立一个测试项目
如上图所示,下载Android Example
运行效果如图
下面我们通过源代码先看看上面的四行显示TextView的获取。
TextView mAppKey = (TextView) findViewById(R.id.tv_appkey); String appKey = ExampleUtil.getAppKey(getApplicationContext()); if (null == appKey) appKey = "AppKey异常"; mAppKey.setText("AppKey: " + appKey);向下追踪,查看getAppKey方法
// 取得AppKey public static String getAppKey(Context context) { Bundle metaData = null; String appKey = null; try { ApplicationInfo ai = context.getPackageManager().getApplicationInfo( context.getPackageName(), PackageManager.GET_META_DATA); if (null != ai) metaData = ai.metaData; if (null != metaData) { appKey = metaData.getString(KEY_APP_KEY); if ((null == appKey) || appKey.length() != 24) { appKey = null; } } } catch (NameNotFoundException e) { } return appKey; }我们可以看到首先通过Context类的getPackageManager()方法获取相关信息。
打开Android源代码可以看到Context实际上是一个抽象类,它的实现类是ContextImpl,类之间的关系如图
有关Context类的介绍请看:http://blog.csdn.net/qinjuning/article/details/7310620
打开ContextImpl类可以看到getPackageManager的实现
@Override
public PackageManager getPackageManager() {
if (mPackageManager != null) {
return mPackageManager;
}
IPackageManager pm = ActivityThread.getPackageManager();
if (pm != null) {
// Doesn't matter if we make more than one instance.
return (mPackageManager = new ApplicationPackageManager(this, pm));
}
return null;
}
上面的ActivityThread才是一个android应用的真正入口,可以在该类中查到main函数。
public static final void main(String[] args) {
SamplingProfilerIntegration.start();
Process.setArgV0("<pre-initialized>");
Looper.prepareMainLooper();
if (sMainThreadHandler == null) {
sMainThreadHandler = new Handler();
}
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
Looper.loop();
if (Process.supportsProcesses()) {
throw new RuntimeException("Main thread loop unexpectedly exited");
}
thread.detach();
String name = (thread.mInitialApplication != null)
? thread.mInitialApplication.getPackageName()
: "<unknown>";
Slog.i(TAG, "Main thread of " + name + " is now exiting");
}
}
有关PackageManager部分的详细介绍请看:
http://blog.csdn.net/stonecao/article/details/6591454
我们现在先不关心怎么获取PackageManager,先来看看PackageManager能干什么
PackageManager类是对所有基于加载信息的数据结构的封装,包括以下功能:
安装,卸载应用查询permission相关信息
查询Application相关信息(application,activity,receiver,service,provider及相应属性等)
查询已安装应用
增加,删除permission
清除用户数据、缓存,代码段等
通过获取ApplicationInfo得到PackageItemInfo类中的Bundle内部类对象
PackageIteminfo类是AndroidManifest.xml文件中所有节点的基类,提供了这些节点的基本信息
在manifest文件中可以看到如下两行代码
<!-- Required . Enable it you can get statistics data with channel --> <meta-data android:name="JPUSH_CHANNEL" android:value="developer-default"/> <meta-data android:name="JPUSH_APPKEY" android:value="5d30bebd28335593a111186" /> <!-- </>值来自开发者平台取得的AppKey-->再看到ExampleUtil中的如下代码应该恍然开朗了吧
public static final String KEY_APP_KEY = "JPUSH_APPKEY";
好啦,下面我们将服务器端推送消息方法改成如下:
MessageResult msgResult = jpush.sendNotificationWithAppKey(sendNo, msgTitle, msgContent);全部代码:
package com.meritit.tuisong.service;
import java.util.HashMap;
import java.util.Map;
import cn.jpush.api.ErrorCodeEnum;
import cn.jpush.api.IOSExtra;
import cn.jpush.api.JPushClient;
import cn.jpush.api.MessageResult;
public class JPushClientExample {
private static final String appKey ="5d30bebd28335593a1345486"; //必填,例如466f7032ac604e02fb7bda89
private static final String masterSecret = "0e0cc80c6f6a4703bec9ed19";//"13ac09b17715bd117163d8a1";//必填,每个应用都对应一个masterSecret
private static JPushClient jpush = null;
/**
* 保存离线的时长。秒为单位。最多支持10天(864000秒)。
* 0 表示该消息不保存离线。即:用户在线马上发出,当前不在线用户将不会收到此消息。
* 此参数不设置则表示默认,默认为保存1天的离线消息(86400秒)。
*/
private static long timeToLive = 60 * 60 * 24;
public static void main(String[] args) {
/*
* Example1: 初始化,默认发送给android和ios,同时设置离线消息存活时间
* jpush = new JPushClient(masterSecret, appKey, timeToLive);
*/
/*
* Example2: 只发送给android
* jpush = new JPushClient(masterSecret, appKey, DeviceEnum.Android);
*/
/*
* Example3: 只发送给IOS
* jpush = new JPushClient(masterSecret, appKey, DeviceEnum.IOS);
*/
/*
* Example4: 只发送给android,同时设置离线消息存活时间
* jpush = new JPushClient(masterSecret, appKey, timeToLive, DeviceEnum.Android);
*/
jpush = new JPushClient(masterSecret, appKey, timeToLive);
/*
* 是否启用ssl安全连接, 可选
* 参数:启用true, 禁用false,默认为非ssl连接
*/
//jpush.setEnableSSL(true);
//测试发送消息或者通知
testSend();
}
private static void testSend() {
// 在实际业务中,建议 sendNo 是一个你自己的业务可以处理的一个自增数字。
// 除非需要覆盖,请确保不要重复使用。详情请参考 API 文档相关说明。
int sendNo = getRandomSendNo();
String msgTitle = "+;//jpush\"\"";
String msgContent = "\\&;w\"\"a--【\npush】";
/*
* IOS设备扩展参数,
* 设置badge,设置声音
*/
Map<String, Object> extra = new HashMap<String, Object>();
IOSExtra iosExtra = new IOSExtra(10, "WindowsLogonSound.wav");
extra.put("ios", iosExtra);
//对所有用户发送通知, 更多方法请参考文档
MessageResult msgResult = jpush.sendNotificationWithAppKey(sendNo, msgTitle, msgContent);
//MessageResult msgResult = jpush.sendCustomMessageWithAppKey(sendNo,msgTitle, msgContent);
//MessageResult msgResult = jpush.sendNotificationWithAlias(sendNo, "a", msgTitle, msgContent);
//覆盖指定msgId的消息,msgId可以从msgResult.getMsgid()获取。
//MessageResult msgResult = jpush.sendNotificationWithAppKey(sendNo, msgTitle, msgContent, 0, extra,msgResult.getMsgid());
if (null != msgResult) {
System.out.println("服务器返回数据: " + msgResult.toString());
if (msgResult.getErrcode() == ErrorCodeEnum.NOERROR.value()) {
System.out.println(String.format("发送成功, sendNo= %s,messageId= %s",msgResult.getSendno(),msgResult.getMsg_id()));
} else {
System.out.println("发送失败, 错误代码=" + msgResult.getErrcode() + ", 错误消息=" + msgResult.getErrmsg());
}
} else {
System.out.println("无法获取数据");
}
}
public static final int MAX = Integer.MAX_VALUE;
public static final int MIN = (int) MAX/2;
/**
* 保持 sendNo 的唯一性是有必要的
* It is very important to keep sendNo unique.
* @return sendNo
*/
public static int getRandomSendNo() {
return (int) (MIN + Math.random() * (MAX - MIN));
}
}
运行结果:
控制台
手机端
这样就可以实现通过自己的服务器来自动生成消息内容了。