Android 实现蓝牙客户端与服务器端通信
发布日期:2021-06-30 22:37:34 浏览次数:2 分类:技术文章

本文共 25191 字,大约阅读时间需要 83 分钟。

一、首先说明:蓝牙通信必须用手机测试,因为avd里没有相关的硬件,会报错!

好了,看看最后的效果图:
这里写图片描述
这里写图片描述

二、概述:

1.判断是否支持Bluetooth

BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();if(bluetoothAdapter == null) {    //the device doesn't support bluetooth} else {    //the device support bluetooth}

2.如果支持,打开Bluetooth

if(!bluetoothAdapter.isEnable()) {    Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);    startActivityForResult(enableIntent,REQUEST_ENABLE_BT);}

3.监视Bluetooth打开状态

BroadcastReceiver bluetoothState = new BroadcastReceiver() {    public void onReceive(Context context, Intent intent) {    String stateExtra = BluetoothAdapter.EXTRA_STATE;       int state = intent.getIntExtra(stateExtra, -1);       switch(state) {    case BluetoothAdapter.STATE_TURNING_ON:        break;    case BluetoothAdapter.STATE_ON:        break;    case BluetoothAdapter.STATE_TURNING_OFF:        break;    case BluetoothAdapter.STATE_OFF:        break;    }    }}registerReceiver(bluetoothState,new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED));

4.设置本地设备可以被其它设备搜索

Intent discoveryIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);startActivityForResult(discoveryIntent,REQUEST_DISCOVERY);BroadcastReceiver discovery = new BroadcastReceiver() {    @Override    public void onRecevie(Content context, Intent intent) {        String scanMode = BluetoothAdapter.EXTRA_SCAN_MODE;        String preScanMode = BluetoothAdapter.EXTRA_PREVIOUS_SCAN_MODE;        int mode = intent.getIntExtra(scanMode);    }}registerReceiver(discovery,new IntentFilter(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);

5.搜索设备

开始搜索 bluetoothAdapter.startDiscovery();
停止搜索 bluetoothAdapter.cancelDiscovery();

当发现一个设备时,系统会发出ACTION_FOUND广播消息,我们可以实现接收这个消息的BroadcastReceiver

BroadcastReceiver deviceFound = new BroadcastReceiver() {    @Override    public void onReceiver(Content content, Intent intent) {        String remoteDeviceName = intent.getStringExtra(BluetoothAdapter.EXTRA_NAME);        BluetoothDevice remoteDevice = intent.getParcelableExtra(BluetoothAdapter.EXTRA_DEVICE);    }}registerReceiver(deviceFound, new IntentFilter(BluetoothAdapter.ACTION_FOUND);

6.连接设备

连接两个蓝牙设备要分别实现服务器端(BluetoothServerSocket)和客户端(BluetoothSocket),这点与J2SE中的

ServerSocket和Socket很类似。

BluetoothServerSocket在服务器端调用方法accept()监听,当有客户端请求到来时,accept()方法返回BluetoothSocket,客户端得到后,两端便可以通信。通过InputStream和OutputStream来实现数据的传输。

accept方法是阻塞的,所以不能放在UI线程中,当用到BluetoothServerSocket和BluetoothSocket时,通常把它们放在各自的新线程中。

三、如何实现

以下是开发中的几个关键步骤:
1)首先开启蓝牙
2)搜索可用设备
3)创建蓝牙socket,获取输入输出流
4)读取和写入数据
5)断开连接关闭蓝牙

1、因为有页面切换,这里我使用了TabHost,但原来的效果不好,没有动画,那只好自己复写了

/** * 带有动画效果的TabHost *  * @Project App_Bluetooth * @Package com.android.bluetooth * @author chenlin * @version 1.0 * @Date 2013年6月2日 * @Note TODO */public class AnimationTabHost extends TabHost {
private int mCurrentTabID = 0;//当前的tabId private final long mDuration = 400;//动画时间 public AnimationTabHost(Context context) { this(context, null); } public AnimationTabHost(Context context, AttributeSet attrs) { super(context, attrs); } /** * 切换动画 */ @Override public void setCurrentTab(int index) { //向右平移 if (index > mCurrentTabID) { TranslateAnimation translateAnimation = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0f, Animation.RELATIVE_TO_SELF, -1.0f, Animation.RELATIVE_TO_SELF, 0f, Animation.RELATIVE_TO_SELF, 0f); translateAnimation.setDuration(mDuration); getCurrentView().startAnimation(translateAnimation); //向左平移 } else if (index < mCurrentTabID) { TranslateAnimation translateAnimation = new TranslateAnimation( Animation.RELATIVE_TO_SELF, 0f, Animation.RELATIVE_TO_SELF, 1.0f, Animation.RELATIVE_TO_SELF, 0f, Animation.RELATIVE_TO_SELF, 0f); translateAnimation.setDuration(mDuration); getCurrentView().startAnimation(translateAnimation); } super.setCurrentTab(index); //-----方向平移------------------------------ if (index > mCurrentTabID) { TranslateAnimation translateAnimation = new TranslateAnimation( // Animation.RELATIVE_TO_PARENT, 1.0f,// RELATIVE_TO_SELF Animation.RELATIVE_TO_PARENT, 0f, Animation.RELATIVE_TO_PARENT, 0f, Animation.RELATIVE_TO_PARENT, 0f); translateAnimation.setDuration(mDuration); getCurrentView().startAnimation(translateAnimation); } else if (index < mCurrentTabID) { TranslateAnimation translateAnimation = new TranslateAnimation( Animation.RELATIVE_TO_PARENT, -1.0f, Animation.RELATIVE_TO_PARENT, 0f, Animation.RELATIVE_TO_PARENT, 0f, Animation.RELATIVE_TO_PARENT, 0f); translateAnimation.setDuration(mDuration); getCurrentView().startAnimation(translateAnimation); } mCurrentTabID = index; }}

2、先搭建好主页,使用复写的TabHost滑动,如何滑动,根据状态,有三种状态

/** * 主页 *  * @Project App_Bluetooth * @Package com.android.bluetooth * @author chenlin * @version 1.0 * @Date 2013年6月2日 */@SuppressWarnings("deprecation")public class BluetoothActivity extends TabActivity {
static AnimationTabHost mTabHost;//动画tabhost static String BlueToothAddress;//蓝牙地址 static Type mType = Type.NONE;//类型 static boolean isOpen = false; //类型: enum Type { NONE, SERVICE, CILENT }; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); initTab(); } private void initTab() { //初始化 mTabHost = (AnimationTabHost) getTabHost(); //添加tab mTabHost.addTab(mTabHost.newTabSpec("Tab1").setIndicator("设备列表", getResources().getDrawable(android.R.drawable.ic_menu_add)) .setContent(new Intent(this, DeviceActivity.class))); mTabHost.addTab(mTabHost.newTabSpec("Tab2").setIndicator("会话列表", getResources().getDrawable(android.R.drawable.ic_menu_add)) .setContent(new Intent(this, ChatActivity.class))); //添加监听 mTabHost.setOnTabChangedListener(new OnTabChangeListener() { public void onTabChanged(String tabId) { if (tabId.equals("Tab1")) { //TODO } } }); //默认在第一个tabhost上面 mTabHost.setCurrentTab(0); } public void onActivityResult(int requestCode, int resultCode, Intent data) { Toast.makeText(this, "address:", Toast.LENGTH_SHORT).show(); }}

3、有了主页,就开始分别实现两个列表页面,一个是寻找设备页面DeviceActivity.java,另一个是会话页面ChatActivity.java

1)设备页面DeviceActivity.java

/** * 发现的设备列表 * @Project    App_Bluetooth * @Package    com.android.bluetooth * @author     chenlin * @version    1.0 * @Date       2013年6月2日 * @Note       TODO */public class DeviceActivity extends Activity {
private ListView mListView; //数据 private ArrayList
mDatas; private Button mBtnSearch, mBtnService; private ChatListAdapter mAdapter; //蓝牙适配器 private BluetoothAdapter mBtAdapter; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.devices); initDatas(); initViews(); registerBroadcast(); init(); } private void initDatas() { mDatas = new ArrayList
(); mAdapter = new ChatListAdapter(this, mDatas); mBtAdapter = BluetoothAdapter.getDefaultAdapter(); } /** * 列出所有的蓝牙设备 */ private void init() { Log.i("tag", "mBtAdapter=="+ mBtAdapter); //根据适配器得到所有的设备信息 Set
deviceSet = mBtAdapter.getBondedDevices(); if (deviceSet.size() > 0) { for (BluetoothDevice device : deviceSet) { mDatas.add(new DeviceBean(device.getName() + "\n" + device.getAddress(), true)); mAdapter.notifyDataSetChanged(); mListView.setSelection(mDatas.size() - 1); } } else { mDatas.add(new DeviceBean("没有配对的设备", true)); mAdapter.notifyDataSetChanged(); mListView.setSelection(mDatas.size() - 1); } } /** * 注册广播 */ private void registerBroadcast() { //设备被发现广播 IntentFilter discoveryFilter = new IntentFilter(BluetoothDevice.ACTION_FOUND); this.registerReceiver(mReceiver, discoveryFilter); // 设备发现完成 IntentFilter foundFilter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); this.registerReceiver(mReceiver, foundFilter); } /** * 初始化视图 */ private void initViews() { mListView = (ListView) findViewById(R.id.list); mListView.setAdapter(mAdapter); mListView.setFastScrollEnabled(true); mListView.setOnItemClickListener(mDeviceClickListener); mBtnSearch = (Button) findViewById(R.id.start_seach); mBtnSearch.setOnClickListener(mSearchListener); mBtnService = (Button) findViewById(R.id.start_service); mBtnService.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { BluetoothActivity.mType = Type.SERVICE; BluetoothActivity.mTabHost.setCurrentTab(1); } }); } /** * 搜索监听 */ private OnClickListener mSearchListener = new OnClickListener() { @Override public void onClick(View arg0) { if (mBtAdapter.isDiscovering()) { mBtAdapter.cancelDiscovery(); mBtnSearch.setText("重新搜索"); } else { mDatas.clear(); mAdapter.notifyDataSetChanged(); init(); /* 开始搜索 */ mBtAdapter.startDiscovery(); mBtnSearch.setText("ֹͣ停止搜索"); } } }; /** * 点击设备监听 */ private OnItemClickListener mDeviceClickListener = new OnItemClickListener() { public void onItemClick(AdapterView
parent, View view, int position, long id) { DeviceBean bean = mDatas.get(position); String info = bean.message; String address = info.substring(info.length() - 17); BluetoothActivity.BlueToothAddress = address; AlertDialog.Builder stopDialog = new AlertDialog.Builder(DeviceActivity.this); stopDialog.setTitle("连接");//标题 stopDialog.setMessage(bean.message); stopDialog.setPositiveButton("连接", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { mBtAdapter.cancelDiscovery(); mBtnSearch.setText("重新搜索"); BluetoothActivity.mType = Type.CILENT; BluetoothActivity.mTabHost.setCurrentTab(1); dialog.cancel(); } }); stopDialog.setNegativeButton("取消", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { BluetoothActivity.BlueToothAddress = null; dialog.cancel(); } }); stopDialog.show(); } }; /** * 发现设备广播 */ private final BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (BluetoothDevice.ACTION_FOUND.equals(action)) { // 获得设备信息 BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); // 如果绑定的状态不一样 if (device.getBondState() != BluetoothDevice.BOND_BONDED) { mDatas.add(new DeviceBean(device.getName() + "\n" + device.getAddress(), false)); mAdapter.notifyDataSetChanged(); mListView.setSelection(mDatas.size() - 1); } // 如果搜索完成了 } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) { setProgressBarIndeterminateVisibility(false); if (mListView.getCount() == 0) { mDatas.add(new DeviceBean("û没有发现蓝牙设备", false)); mAdapter.notifyDataSetChanged(); mListView.setSelection(mDatas.size() - 1); } mBtnSearch.setText("重新搜索"); } } }; @Override public void onStart() { super.onStart(); if (!mBtAdapter.isEnabled()) { Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult(enableIntent, 3); } } @Override protected void onDestroy() { super.onDestroy(); if (mBtAdapter != null) { mBtAdapter.cancelDiscovery(); } this.unregisterReceiver(mReceiver); }}

2)会话页面ChatActivity.java

/** * 会话界面 *  * @Project App_Bluetooth * @Package com.android.bluetooth * @author chenlin * @version 1.0 * @Date 2013年3月2日 * @Note TODO */public class ChatActivity extends Activity implements OnItemClickListener, OnClickListener {
private static final int STATUS_CONNECT = 0x11; private ListView mListView; private ArrayList
mDatas; private Button mBtnSend;// 发送按钮 private Button mBtnDisconn;// 断开连接 private EditText mEtMsg; private DeviceListAdapter mAdapter; /* 一些常量,代表服务器的名称 */ public static final String PROTOCOL_SCHEME_L2CAP = "btl2cap"; public static final String PROTOCOL_SCHEME_RFCOMM = "btspp"; public static final String PROTOCOL_SCHEME_BT_OBEX = "btgoep"; public static final String PROTOCOL_SCHEME_TCP_OBEX = "tcpobex"; // 蓝牙服务端socket private BluetoothServerSocket mServerSocket; // 蓝牙客户端socket private BluetoothSocket mSocket; // 设备 private BluetoothDevice mDevice; private BluetoothAdapter mBluetoothAdapter; // --线程类----------------- private ServerThread mServerThread; private ClientThread mClientThread; private ReadThread mReadThread; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.chat); initDatas(); initViews(); initEvents(); } private void initEvents() { mListView.setOnItemClickListener(this); // 发送信息 mBtnSend.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { String text = mEtMsg.getText().toString(); if (!TextUtils.isEmpty(text)) { // 发送信息 sendMessageHandle(text); mEtMsg.setText(""); mEtMsg.clearFocus(); // 隐藏软键盘 InputMethodManager manager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); manager.hideSoftInputFromWindow(mEtMsg.getWindowToken(), 0); } else Toast.makeText(ChatActivity.this, "发送内容不能为空!", Toast.LENGTH_SHORT).show(); } }); // 关闭会话 mBtnDisconn.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { if (BluetoothActivity.mType == Type.CILENT) { shutdownClient(); } else if (BluetoothActivity.mType == Type.SERVICE) { shutdownServer(); } BluetoothActivity.isOpen = false; BluetoothActivity.mType = Type.NONE; Toast.makeText(ChatActivity.this, "已断开连接!", Toast.LENGTH_SHORT).show(); } }); } private void initViews() { mListView = (ListView) findViewById(R.id.list); mListView.setAdapter(mAdapter); mListView.setFastScrollEnabled(true); mEtMsg = (EditText) findViewById(R.id.MessageText); mEtMsg.clearFocus(); mBtnSend = (Button) findViewById(R.id.btn_msg_send); mBtnDisconn = (Button) findViewById(R.id.btn_disconnect); } private void initDatas() { mDatas = new ArrayList
(); mAdapter = new DeviceListAdapter(this, mDatas); mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); } /** * 信息处理 */ private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { String info = (String) msg.obj; switch (msg.what) { case STATUS_CONNECT: Toast.makeText(ChatActivity.this, info, 0).show(); break; } if (msg.what == 1) { mDatas.add(new DeviceBean(info, true)); mAdapter.notifyDataSetChanged(); mListView.setSelection(mDatas.size() - 1); }else { mDatas.add(new DeviceBean(info, false)); mAdapter.notifyDataSetChanged(); mListView.setSelection(mDatas.size() - 1); } } }; @Override public void onResume() { super.onResume(); if (BluetoothActivity.isOpen) { Toast.makeText(this, "连接已经打开,可以通信。如果要再建立连接,请先断开", Toast.LENGTH_SHORT).show(); return; } if (BluetoothActivity.mType == Type.CILENT) { String address = BluetoothActivity.BlueToothAddress; if (!"".equals(address)) { mDevice = mBluetoothAdapter.getRemoteDevice(address); mClientThread = new ClientThread(); mClientThread.start(); BluetoothActivity.isOpen = true; } else { Toast.makeText(this, "address is null !", Toast.LENGTH_SHORT).show(); } } else if (BluetoothActivity.mType == Type.SERVICE) { mServerThread = new ServerThread(); mServerThread.start(); BluetoothActivity.isOpen = true; } } // 客户端线程 private class ClientThread extends Thread {
public void run() { try { mSocket = mDevice.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB")); Message msg = new Message(); msg.obj = "请稍候,正在连接服务器:" + BluetoothActivity.BlueToothAddress; msg.what = STATUS_CONNECT; mHandler.sendMessage(msg); mSocket.connect(); msg = new Message(); msg.obj = "已经连接上服务端!可以发送信息。"; msg.what = STATUS_CONNECT; mHandler.sendMessage(msg); // 启动接受数据 mReadThread = new ReadThread(); mReadThread.start(); } catch (IOException e) { Message msg = new Message(); msg.obj = "连接服务端异常!断开连接重新试一试。"; msg.what = STATUS_CONNECT; mHandler.sendMessage(msg); } } }; // 开启服务器 private class ServerThread extends Thread {
public void run() { try { // 创建一个蓝牙服务器 参数分别:服务器名称、UUID mServerSocket = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(PROTOCOL_SCHEME_RFCOMM, UUID.fromString("00001101-0000-1000-8000-00805F9B34FB")); Message msg = new Message(); msg.obj = "请稍候,正在等待客户端的连接..."; msg.what = STATUS_CONNECT; mHandler.sendMessage(msg); /* 接受客户端的连接请求 */ mSocket = mServerSocket.accept(); msg = new Message(); msg.obj = "客户端已经连接上!可以发送信息。"; msg.what = STATUS_CONNECT; mHandler.sendMessage(msg); // 启动接受数据 mReadThread = new ReadThread(); mReadThread.start(); } catch (IOException e) { e.printStackTrace(); } } }; /* 停止服务器 */ private void shutdownServer() { new Thread() { public void run() { if (mServerThread != null) { mServerThread.interrupt(); mServerThread = null; } if (mReadThread != null) { mReadThread.interrupt(); mReadThread = null; } try { if (mSocket != null) { mSocket.close(); mSocket = null; } if (mServerSocket != null) { mServerSocket.close(); mServerSocket = null; } } catch (IOException e) { Log.e("server", "mserverSocket.close()", e); } }; }.start(); } /* ͣ停止客户端连接 */ private void shutdownClient() { new Thread() { public void run() { if (mClientThread != null) { mClientThread.interrupt(); mClientThread = null; } if (mReadThread != null) { mReadThread.interrupt(); mReadThread = null; } if (mSocket != null) { try { mSocket.close(); } catch (IOException e) { e.printStackTrace(); } mSocket = null; } }; }.start(); } // 发送数据 private void sendMessageHandle(String msg) { if (mSocket == null) { Toast.makeText(this, "没有连接", Toast.LENGTH_SHORT).show(); return; } try { OutputStream os = mSocket.getOutputStream(); os.write(msg.getBytes()); mDatas.add(new DeviceBean(msg, false)); mAdapter.notifyDataSetChanged(); mListView.setSelection(mDatas.size() - 1); } catch (IOException e) { e.printStackTrace(); } } // 读取数据 private class ReadThread extends Thread {
public void run() { byte[] buffer = new byte[1024]; int bytes; InputStream is = null; try { is = mSocket.getInputStream(); while (true) { if ((bytes = is.read(buffer)) > 0) { byte[] buf_data = new byte[bytes]; for (int i = 0; i < bytes; i++) { buf_data[i] = buffer[i]; } String s = new String(buf_data); Message msg = new Message(); msg.obj = s; msg.what = 1; mHandler.sendMessage(msg); } } } catch (IOException e1) { e1.printStackTrace(); } finally { try { is.close(); } catch (IOException e1) { e1.printStackTrace(); } } } } @Override public void onItemClick(AdapterView
parent, View view, int position, long id) { } @Override public void onClick(View view) { } @Override protected void onDestroy() { super.onDestroy(); if (BluetoothActivity.mType == Type.CILENT) { shutdownClient(); } else if (BluetoothActivity.mType == Type.SERVICE) { shutdownServer(); } BluetoothActivity.isOpen = false; BluetoothActivity.mType = Type.NONE; }}

三、相关代码下载

链接: 密码:awgv

—————————————————————————————————————————————————–

java架构师项目实战,高并发集群分布式,大数据高可用视频教程,共760G

下载地址:

https://item.taobao.com/item.htm?id=56273996582

01.高级架构师四十二个阶段高

02.Java高级系统培训架构课程148课时
03.Java高级互联网架构师课程
04.Java互联网架构Netty、Nio、Mina等-视频教程
05.Java高级架构设计2016整理-视频教程
06.架构师基础、高级片
07.Java架构师必修linux运维系列课程
08.Java高级系统培训架构课程116课时
+
hadoop系列教程,java设计模式与数据结构, Spring Cloud微服务, SpringBoot入门

内容详情:

【入门篇】

J2SE的Socket网络编程应用
J2SE的反射机制高级应用
J2SE高深讲解
JAVA编程思想 中级教程
JAVA编程思想 初级教程
JAVA编程思想 高级教程
基于J2SE的QQ聊天工具开发
我来说说面向对象
【进阶篇】
CRM项目
Eclipse
Hibernate
JAVA WEB开发视频
JAVAWEB开发实战经典-高级案例篇
JAVAWEB
JAVA线程并发教程
java网上在线支付实战视频
java设计模式
jdbc
junit
mybatis
spring mvc
SpringMvc+Spring+MyBatis+Maven整合视频
SpringMVC
Spring
Struts2 开发实战讲解
Struts2+Spring3+Hibernate4+Maven+EasyUI整合入门视频
Struts
SVN
tomcat
weblogic
WebService从入门到上手企业开发
企业系统OA办公自动化
手机进销存系统
数据结构和算法视频
设计模式系列
【高级篇】
Cas单点登录
Extjs4.1+Spring3.2+hibernate4.1+MySql5商城
Git权威指南
groovy入门视频
Java 8新特性
Lucene
Mongodb
node.js
Nutch相关框架
OA办公自动化系统
Quartz Job定时任务
Solr高级应用视频
Spring Security权限控制
Spring源码解读与设计详析
Struts2源码剖析与架构指导
大型CMS内容管理系统项目
微信入门视频
深入JVM内核—原理、诊断与优化
深入浅出微信公众平台实战开发(微网站、LBS云、Api接口调用、服务号高级接口)
银行接口资料
【架构篇】
ActiveMQ实战
Apache-Tomcat集群搭建
Linux集群
Linux高级架构架构方案及实现指南
Memcached分布式集群
Mysql特级优化课程
Nginx+Tomcat+Memcached群集配置软件包
Nginx服务器搭建
Nginx网站架构实战(Web服务器负载均衡与反向代理)
SOA Dubbo
storm入门到精通
storm集群的搭建
storm项目实战
UML建模
互联网公司技术架构系列
京东B2C平台推荐搜索的实践和思考
京东大数据分析与创新应用
京东大规模存储持续研发
京东电商海量订单处理OFC系统的关键技术
优米网架构设计方案
基于SOA 思想下的百万数据架构
大型网站提速之MySQL优化
大型网站架构设计
大数据高并发架构实战案例
数据优化技术Redis
数据库高并发原理
深入Java程序性能调优
深入浅出MongoDB应用实战集群及系统架构
深度揭秘服务器端内幕
电商网站之Solr应用
系统架构设计师
阿里分布式数据库服务实践
—————————————————————————————————————————————————–

转载地址:https://lovoo.blog.csdn.net/article/details/51576246 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:Android 几何图形工具类GeometryUtil
下一篇:Android 实现简单的分页

发表评论

最新留言

很好
[***.229.124.182]2024年04月06日 08时02分42秒