Android 基于Socket的长连接实现一个实时推送的功能

实现此功能需要考虑的几点:

1)如何保证Socket长连接一直存在并有效运行

2)通过Service运行Socket,当服务端有数据时,通过广播或者handler来更新UI


具体效果,来上代码:

@Override
	public void run() {
		try {
			loginService();
		} catch (IOException ex) {
			ex.printStackTrace();
			isConnected = false;
			sendStatus("Socket连接失败!");
			send("Socket连接失败!");
		}
		int i = 0;
		while (true) {
			if (stopService) {
				return;
			}
			try {
				if (isConnected && socket != null && socket.isConnected()) {
					try {
						socket.sendUrgentData(0xFF);// 发送检测socket连接包
					} catch (Exception ex) {
						sendStatus("Socket连接已断开!");
						isConnected = false;
					}
					if (isConnected && !socket.isInputShutdown()) {
						String data = in.readLine();// 线程阻塞接受完毕后向下执行
						if (Utils.isAppOnForeground(mContext)) {
							Intent intent = new Intent("GET_ROMETE_DATA");
							intent.putExtra("msg", data);
							mContext.sendBroadcast(intent);
						} else {
							// 发送通知
							send(data);
							// 将数据缓存起来
							Utils.writeSDFile(mContext.getFilesDir()
									+ Utils.CACHEDIR, data + "-----time:"
									+ Utils.getTime() + "\n");
						}
					}
				} else {
					i++;
					loginService();
				}
			} catch (Exception e) {
				sendStatus("Socket连接失败!");
				e.printStackTrace();
			} finally {
				if (!isConnected && i == 3) {
					i = 0;
					try {
						Thread.sleep((long) ((Math.random() * 300) * 1000));
					} catch (InterruptedException e) {
						e.printStackTrace();
					}// 当前线程休眠随机分钟之内休眠之后再次登錄
				} else {
					try {
						Thread.sleep(5000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		}
	}

连接Socket代码:

// 这里获得本地配置的ip和端口
		String host = (String) PushSharePerfance.getInstance(mContext)
				.getValue(PushSharePerfance.LOGIN_HOST, "String");
		int port = (Integer) PushSharePerfance.getInstance(mContext).getValue(
				PushSharePerfance.LOGIN_PORT, "Integer");
		if (TextUtils.isEmpty(host) || port == 0) {
			socket = new Socket(HOST, PORT);
		} else if (!TextUtils.isEmpty(host) && port != 0) {
			socket = new Socket(host, port);
		}
		in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
		out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(
				socket.getOutputStream())), true);
		String data = "{\"cmd\":\"connect\",\"userId\":\"123\"}";
		if (socket.isConnected()) {
			if (!socket.isOutputShutdown()) {
				out.print(data);
				out.flush();
				isConnected = true;
				Log.d(TAG, "-------" + data + "-----send  login----");
				sendStatus("Socket连接成功!");
			}
		}


通过系统闹钟心跳来维持长连接

// 通过系统闹钟来维持长连接心跳
	private void keepConnect() {
		// 创建Intent对象,action为ELITOR_CLOCK
		Intent heartbeatIntent = new Intent("ELITOR_CLOCK");
		Intent intent = new Intent(this, SocketService.class);

		// 定义一个PendingIntent对象,PendingIntent.getBroadcast包含了sendBroadcast的动作。
		PendingIntent pi = PendingIntent.getService(this, 0, intent, 0);
		PendingIntent beatIntent = PendingIntent.getBroadcast(this, 0,
				heartbeatIntent, 0);
		// AlarmManager对象,注意这里并不是new一个对象,Alarmmanager为系统级服务
		AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);

		// 设置闹钟从当前时间开始,每隔5s执行一次PendingIntent对象pi,注意第一个参数与第二个参数的关系
		am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(),
				30 * 1000, pi);
		// am.setRepeating(AlarmManager.RTC_WAKEUP,
		// System.currentTimeMillis() + 60 * 1000, 60 * 1000, beatIntent);
	}

如此,一个通过Socket长连接的方式可以模拟一个在线推送的功能







  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值