最近学习了Android的消息推送。一开始一直以为很复杂,没想到消息推送也分为两种方式一种是长链接,比如现在的即时通讯,基于XMPP、MQTT协议的消息推送。一种是短链接方式,实现的原理是android开机启动服务,定时调戏(就是访问的意思)服务器,服务器json形式返回数据,客户端再解析数据,把内容显示在通知栏栏,点击通知栏跳到指定的html页面上。上面总结下来就是短链接的Android端消息推送方式。接下来看怎么做!

       1,建立一个web项目,作为练习的服务器。如下图所示

      

android中的消息推送 安卓实现消息推送_android中的消息推送

     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中的消息推送 安卓实现消息推送_System_02


点击通知栏访问指定页面效果图:

android中的消息推送 安卓实现消息推送_android中的消息推送_03

服务端收到android端的请求,打印在控制台的信息如图

android中的消息推送 安卓实现消息推送_消息推送_04


最后希望对大家有用