最近学习了Android的消息推送。一开始一直以为很复杂,没想到消息推送也分为两种方式一种是长链接,比如现在的即时通讯,基于XMPP、MQTT协议的消息推送。一种是短链接方式,实现的原理是android开机启动服务,定时调戏(就是访问的意思)服务器,服务器json形式返回数据,客户端再解析数据,把内容显示在通知栏栏,点击通知栏跳到指定的html页面上。上面总结下来就是短链接的Android端消息推送方式。接下来看怎么做!
1,建立一个web项目,作为练习的服务器。如下图所示
2,创建一个Servlet,定义以Json的形式返回。
public class UserServelt extends HttpServlet {
public UserServelt() {
super();
}
public void destroy() {
super.destroy();
}
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doPost(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("hahha");
response.setContentType("text/html");
response.setCharacterEncoding("utf-8");
String title = "标题";
String content ="内容";
String http = "http://www.baidu.com";
PrintWriter out = response.getWriter();
JSONObject json = new JSONObject();
json.put("title", title);
json.put("content",content);
json.put("http",http);
out.println(json);
out.flush();
out.close();
}
3,做完web端,回到android,建立一个android项目
4,因为作为消息推送,当手机APP没有运行,手机是开启状态时,也可以接收到服务器推送的消息。所以,我们在设置一个开机广播,当手机开机后,启动一个定时服务,访问服务器指定的地址。开机广播代码如下。特别注意的是,需要在清单文件中注册开机广播,并且添加权限<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>。
public class BootReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
System.out.println("------------------看看你有木有动静-----------------");
Intent service = new Intent(context,RunningService.class);
context.startService(service);
} }
5,后台服务是通过定时器来完成,每隔1分钟访问服务器拿到数据。通过Timer、TimerTask和handler来完成。
private void timerTask() {
Timer timer = new Timer();
TimerTask task = new TimerTask() {
@Override
public void run() {
Message msg = new Message();
//访问http操作
try {
String path = "http://192.168.1.110:8080/APP/servlet/UserServelt";
String result = HttpToServier.connect2(path); //获取json数据,把数据传给显示在通知栏的类中。
System.out.println("----------------------------result--------------------"+result);
msg.obj = result;
handler.sendMessage(msg);//发送数据
} catch (Exception e) {
e.printStackTrace();
}
}
};
timer.schedule(task, systemDate, 60000);//每隔一分钟访问
}
6.服务器返回的数据通过JSON解析,发送给通知栏
try {
json = new JSONObject((String) msg.obj);
title = json.getString("title");
content = json.getString("content");
url = json.getString("http");
} catch (JSONException e1) {
e1.printStackTrace();
}
7,定义一个通知栏,显示服务器返回的数据
//获取状态通知栏管理
NotificationManager mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
//获取通知栏构造器Builder
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this);
//初始化通知栏
mBuilder.setContentTitle(title)
.setContentText(content)
.setContentIntent(getDefalutIntent(Notification.FLAG_AUTO_CANCEL,url))
.setNumber(5)//显示数量
.setTicker(url)//通知首次出现在通知栏,带上升动画效果的
.setWhen(System.currentTimeMillis())//通知产生的时间,会在通知信息里显示
.setPriority(Notification.PRIORITY_DEFAULT)//设置该通知优先级
.setAutoCancel(true)//设置这个标志当用户单击面板就可以让通知将自动取消
.setOngoing(false)//ture,设置他为一个正在进行的通知。他们通常是用来表示一个后台任务,用户积极参与(如播放音乐)或以某种方式正在等待,因此占用设备(如一个文件下载,同步操作,主动网络连接)
.setDefaults(Notification.DEFAULT_VIBRATE)//向通知添加声音、闪灯和振动效果的最简单、最一致的方式是使用当前的用户默认设置,使用defaults属性,可以组合:
//Notification.DEFAULT_ALL Notification.DEFAULT_SOUND 添加声音 // requires VIBRATE permission
.setSmallIcon(R.drawable.ic_launcher);
mNotificationManager.notify(1,mBuilder.build()); //显示
8,访问服务器我用了两种方式一种是httpclient方式,一种是post的方式,你可以根据自己的喜爱挑一种
public static String connect2(String url) throws Exception{
HttpClient httpClient = new DefaultHttpClient();
HttpPost post = new HttpPost(new URI(url));
HttpResponse httpResponse = httpClient.execute(post);
//如果服务器成功返回响应
if(httpResponse.getStatusLine().getStatusCode() == 200){
HttpEntity entity = httpResponse.getEntity();
if(entity != null){
//获取服务器返回的数据
result = EntityUtils.toString(entity,"UTF-8");
System.out.print("服务器返回的代码"+result);
}
}else{
System.out.println("连接超时");
}
return result;
}
public static String connect(URL url){
InputStream inputStream = null;
HttpURLConnection connection = null;
StringBuffer sb = null;
System.out.println("--------------------------准备----------------------");
try {
connection = (HttpURLConnection) url.openConnection();//打开链接
System.out.println("--------------------------开始----------------------");
connection.setConnectTimeout(3000); //连接超时
connection.setRequestMethod("POST");//连接请求方式
connection.setDoInput(true);//设置是否从httpUrlConnection读入
connection.setDoOutput(true);//设置是否向httpUrlConnection输出
// connection.setRequestProperty("Connection", "Keep-Alive");//请求属性
connection.connect();//连接
System.out.println("--------------------------马上了----------------------");
if(connection.getResponseCode() == 200){
System.out.println("--------------------------hhaha----------------------");
inputStream = connection.getInputStream();
Reader reader = new InputStreamReader(inputStream,"UTF-8");//获取流
BufferedReader bufferedReader = new BufferedReader(reader);
String str = null;
sb = new StringBuffer();
while((str = bufferedReader.readLine()) != null){//读取流
sb.append(str);
}
}
} catch (IOException e) {
e.printStackTrace();
} finally{
if(inputStream != null){
try {
inputStream.close();
inputStream = null;
} catch (IOException e) {
e.printStackTrace();
}
}
}
if(sb != null){
return new String(sb);
}
return null;
}
9,需要注意的是需要在清单文件中添加访问网络的权限<uses-permission android:name="android.permission.INTERNET"/>,真机上运行必须在同一个局域网内
10,程序运行后的效果图如下,程序主界面和收到服务器返回的数据通过通知栏显示效果图
点击通知栏访问指定页面效果图:
服务端收到android端的请求,打印在控制台的信息如图
最后希望对大家有用