簡單的 websocket


項目由於要實現一些自主定位推送,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")));

客戶端發送什麼唯一標識來給服務端 請行約定好即可。 我這裏是推薦手機標識符+時間戳+隨機數;




如果有更多優化會繼續更新的。代碼全在這裏。

發佈了38 篇原創文章 · 獲贊 13 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章