项目由于要实现一些自主定位推送,tcp协议后台不知怎么搭不上,决定还是换成http协议 用websocket 去实现推送。当时我是懵的,没去了解过这个websocket,和同事花了一下时间搞懂了一部分,深入的东西项目里没用到就先过了。
需要的jar 包 Java-WebSocket-1.3.1-SNAPSHOT.jar
直接上代码
ClientReceiver.java
package com.qpp.websocketPush;
import java.io.Serializable;
import java.util.List;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import com.qpbox.R;
import com.qpp.MainActivity;
import com.qpp.entity.Comment;
import com.qpp.http.XHLog;
import android.annotation.SuppressLint;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.NotificationCompat.Builder;
import android.util.Log;
import android.widget.RemoteViews;
public class ClientReceiver extends BroadcastReceiver {
public static final String LOGIN_BOX = "com.box";
public static final String LOGIN_USER = "";
public static final String LOGIN_LOACTION = "";
public static final String MSG_SERVICE = "";
/** Notification构造器 */
NotificationCompat.Builder mBuilder;
/** Notification的ID */
int notifyId = 100;
/** Notification管理 */
public NotificationManager mNotificationManager;
public Context context;
//public PushBean push;
public String MsgContent;
public int MsgType;
public String MsgImgpath;
private List<WPush> content;
@SuppressLint("NewApi")
@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
// String action = intent.getAction();
System.out.println("接受到广播");
this.context = context;
initNotify();
mNotificationManager = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);// 获取系统通知的服务
// push = new PushBean();
Object msg = intent.getExtras().get("msg");
Log.e(ClientReceiver.class.getName(), msg.toString());
if (msg instanceof String) {
deal_string(msg.toString());
} else if (msg instanceof Serializable) {
deal_serializable((Serializable) msg);
}
}
private void deal_serializable(Serializable serializable) {
// showIntentActivityNotify(serializable.toString());
showIntentActivityNotify(serializable.toString());
System.out.println("11111");
}
// / {"type":1,"msg":{}} type 类型 0 1 2 3 4 5 6 接收后台传来的数据 json 解析 设置到通知里
private void deal_string(String string) {
XHLog.e("json", string);
// try {
// JSONObject jo = new JSONObject(string);
// String mainTitle = jo.getString("mainTitle");
// String secondaryTitle =jo.getString("secondaryTitle");
// int fd= jo.getInt("fd");
// int type = jo.getInt("type");
// //if (code == 200) {
// if(type==1){
//
// JSONArray jsonArray = jo.getJSONArray("content");
// String contenttext = jsonArray.getString(0);
// }
// if(type==2){
// JSONArray jsonArray = jo.getJSONArray("content");
// for (int i = 0; i < jsonArray.length(); i++) {
// content.add(WPush.getpush(jsonArray
// .getJSONObject(i)));
// }
// }
// if(type==3){
// JSONArray jsonArray = jo.getJSONArray("content");
// String webpath = jsonArray.getString(0);
// }
// } catch (JSONException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
showIntentActivityNotify(string);
}
public PendingIntent getDefalutIntent(int flags) {
PendingIntent pendingIntent = PendingIntent.getActivity(context, 1,
new Intent(), flags);
return pendingIntent;
}
public void showIntentActivityNotify(String text) {
// Notification.FLAG_ONGOING_EVENT --设置常驻
// Flag;Notification.FLAG_AUTO_CANCEL 通知栏上点击此通知后自动清除此通知
// notification.flags = Notification.FLAG_AUTO_CANCEL;
// //在通知栏上点击此通知后自动清除此通知
try {
// mBuilder = new NotificationCompat.Builder(context);
mBuilder.setAutoCancel(true)
// 点击后让通知将消失
.setContentTitle("name").setContentText(text)
.setSmallIcon(R.drawable.ico_qpp).setTicker("有新的更新");
// 点击的意图ACTION是跳转到Intent
Intent resultIntent = new Intent(context, MainActivity.class);
resultIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0,
resultIntent, PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.setContentIntent(pendingIntent);
mNotificationManager.notify(notifyId, mBuilder.build());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 初始化通知栏 "192.168.1.103"
* */
private void initNotify() {
mBuilder = new NotificationCompat.Builder(context);
mBuilder.setContentTitle("name")
.setContentText("name有新的更新")
.setContentIntent(
getDefalutIntent(Notification.FLAG_AUTO_CANCEL))
// .setNumber(number)//显示数量
.setTicker("测试通知来啦")// 通知首次出现在通知栏,带上升动画效果的
.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);
}
}
QppWebsocket.java
package com.qpp.websocketPush;
import java.io.Serializable;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.drafts.Draft;
import org.java_websocket.drafts.Draft_17;
import org.java_websocket.framing.Framedata;
import org.java_websocket.handshake.ServerHandshake;
import com.qpp.QPPApplication;
import com.qpp.http.XHLog;
import com.qpp.util.NetworkManagement;
import android.app.Application;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
public class QppWebsocket extends WebSocketClient {
private Context context;
private static QppWebsocket websocket;
public static boolean Websocket_exit = false;
public boolean is_conn = false;
public QppWebsocket(URI serverUri, Draft draft, Context context) {
super(serverUri, draft);
this.context = context;
}
public QppWebsocket(URI serverURI) {
super(serverURI);
}
public static QppWebsocket webSocket(URI serverUri, Draft draft,
Application context) {
if (websocket != null) {
websocket.close();
websocket = null;
}
if (websocket == null) {
synchronized (QppWebsocket.class.getName()) {
if (websocket == null) {
websocket = new QppWebsocket(serverUri, draft, context);
}
}
}
return websocket;
}
@Override
public void onOpen(ServerHandshake handshakedata) {
System.out.println("opened connection");
is_conn = true;
// if you plan to refuse connection based on ip or httpfields
// overload:onWebsocketHandshakeReceivedAsClient
}
<span style="white-space:pre"> </span>//接受到消息时处理
@Override
public void onMessage(String message) {
System.out.println("received: " + message);
Intent intent = new Intent();
intent.setAction("com.qpbox");
Log.e("=========", "走没走");
if (message instanceof String) {
intent.putExtra("msg", message);
} else if (message instanceof Serializable) {
Serializable s = (Serializable) message;
intent.putExtra("msg", s);
}
context.sendOrderedBroadcast(intent, null); // 有序广播发送
// Toast.makeText(context, "发送广播成功", Toast.LENGTH_SHORT).show();
}
@Override
public void onFragment(Framedata fragment) {
System.out.println("received fragment: "
+ new String(fragment.getPayloadData().array()));
}
<span style="white-space:pre"> </span>//websocket 断开时处理
@Override
public void onClose(int code, String reason, boolean remote) {
// The codecodes are documented in class
// org.java_websocket.framing.CloseFrame
is_conn = false;
System.out.println("Connection closed by "
+ (remote ? "remote peer" : "us"));
<span style="white-space:pre"> </span>//重连
conn();
if (Websocket_exit) {
}
}
<span style="white-space:pre"> </span>//websocket有错误时处理
@Override
public void onError(Exception ex) {
ex.printStackTrace();
// if the error is fatal then onClose will be called additionally
}
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
XHLog.e("!!!!!!!", "XXXXXXXXXXXXXXXXXXXXXXX");
conn();
}
};
<span style="white-space:pre"> </span>//重连方法
public synchronized void conn() {
if (!NetworkManagement.isNetworkAvailable(QPPApplication.context)) {
handler.sendEmptyMessageDelayed(0, 5000);
} else {
try {
URI uri = new URI("http://mpp.7pa.com:9503");
Draft_17 draft = new Draft_17();
QPPApplication.websocket = QppWebsocket.webSocket(uri,
new Draft_17(), QPPApplication.context);
QPPApplication.websocket.connectBlocking();
int size = msgs.size();
for (int i = 0; i < size; i++) {
sendMsg(msgs.get(i));
}
msgs.removeAll(msgs);
} catch (Exception e) {
// TODO: handle exception
handler.sendEmptyMessageDelayed(0, 5000); //每5秒重连一次
e.printStackTrace();
}
}
}
private List<String> msgs = new ArrayList<String>();
// 客户端发送消息
public synchronized void sendMsg(String string) {
if (QPPApplication.websocket.is_conn)
QPPApplication.websocket.send(string);
else {
if (msgs.indexOf(string) < 0)
msgs.add(string);
}
}
<span style="white-space:pre"> </span>//重新websocket的连接的方法 使用标签 is_conn true表示已经连接 不会调用重连的方法
@Override
public boolean connectBlocking() throws InterruptedException {
// TODO Auto-generated method stub
if (is_conn)
return is_conn;
return super.connectBlocking();
}
}
在Application中初始化 并连接
// websocket
try {
uri = new URI("服务器ip或者域名"); //例如:http://rdp.7wa.com:5503
Draft_17 draft = new Draft_17();
websocket = QppWebsocket.webSocket(uri, new Draft_17(), this);
Field field = websocket.getClass().getDeclaredField("engine");
field.set(websocket, new MyWebSocketImpl(websocket, draft));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
<!-- websocket -->
<receiver
android:name="com.qpp.websocketPush.ClientReceiver"
>
<intent-filter android:priority="1000"
>
<action android:name="com.qpbox"/>
</intent-filter>
</receiver>
如果是要用户登录时客户端发送消息到服务器后服务器对登录用户进行针对推送
在登录成功的方法里调用
QPPApplication.websocket.connectBlocking();
QPPApplication.websocket.sendMsg(map_2_json(login("14778327", "0", "62236824340")));
客户端发送什么唯一标识来给服务端 请行约定好即可。 我这里是推荐手机标识符+时间戳+随机数;
如果有更多优化会继续更新的。代码全在这里。