phoneGap蓝牙设备链接打印操作插件

前台 bluetooth.js

/*
Copyright 2013  101.key

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CO NDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/


var Bluetooth = function() {};


/**
* 判断蓝牙设备启用

* @param successCallback:true or false
* @param failureCallback:error message
*/
Bluetooth.prototype.isBTEnabled = function(successCallback, failureCallback) {
  return cordova.exec(successCallback, failureCallback, 'BluetoothPlugin', 'isBTEnabled', []);
};

/**
* 启用蓝牙设备

* @param successCallback:true
* @param failureCallback:error message
*/
Bluetooth.prototype.enableBT = function(successCallback,failureCallback) {
  return cordova.exec(successCallback, failureCallback, 'BluetoothPlugin', 'enableBT', []);
}

/**
* 禁用蓝牙设备

* @param successCallback:true
* @param failureCallback:error message
*/
Bluetooth.prototype.disableBT = function(successCallback,failureCallback) {
  return cordova.exec(successCallback, failureCallback, 'BluetoothPlugin', 'disableBT', []);
}

/**
* 开始蓝牙设备搜索

* @param successCallback:JSONArray {'name':'address',...}
* @param failureCallback:error message
*/
Bluetooth.prototype.discoverDevices = function(successCallback, failureCallback) {
  return cordova.exec(successCallback, failureCallback, 'BluetoothPlugin', 'discoverDevices', []);
}

/**
* 停止蓝牙设备搜索

* @param successCallback:true or false
* @param failureCallback:error message
*/
Bluetooth.prototype.stopDiscoverDevices = function(successCallback, failureCallback) {
  return cordova.exec(successCallback, failureCallback, 'BluetoothPlugin', 'stopDiscoverDevices', []);
}

/**
* 蓝牙设备是否已绑定

* @param successCallback:true or false
* @param failureCallback:error message
* @param address:设备物理地址
*/
Bluetooth.prototype.isBoundBT = function(successCallback, failureCallback, address) {
  return cordova.exec(successCallback, failureCallback, 'BluetoothPlugin', 'isBoundBT', [address]);
};

/**
* 绑定蓝牙设备

* @param successCallback:true or false
* @param failureCallback:error message
* @param address:设备物理地址
*/
Bluetooth.prototype.boundBT = function(successCallback, failureCallback, address) {
  return cordova.exec(successCallback, failureCallback, 'BluetoothPlugin', 'boundBT', [address]);
};

/**
* 解除蓝牙设备绑定

* @param successCallback:true or false
* @param failureCallback:error message
*/
Bluetooth.prototype.unBoundBT = function(successCallback, failureCallback, address) {
  return cordova.exec(successCallback, failureCallback, 'BluetoothPlugin', 'unBoundBT', [address]);
};

/**
* 列出所有已绑定的蓝牙设备

* @param successCallback:JSONArray {'name':'address',...}
* @param failureCallback:error message
*/
Bluetooth.prototype.listBoundDevices = function(successCallback, failureCallback) {
  return cordova.exec(successCallback, failureCallback, 'BluetoothPlugin', 'listBoundDevices', []);
};

/**
* 蓝牙设备是否已链接

* @param successCallback:true
* @param failureCallback:error message
* @param address:设备物理地址
*/
Bluetooth.prototype.isConnect = function(successCallback, failureCallback, address) {
  return cordova.exec(successCallback, failureCallback, 'BluetoothPlugin', 'isConnect', [address]);
};

/**
* 链接蓝牙设备

* @param successCallback:success message
* @param failureCallback:error message
* @param address:设备物理地址
*/
Bluetooth.prototype.connect = function(successCallback, failureCallback, address) {
  return cordova.exec(successCallback, failureCallback, 'BluetoothPlugin', 'connect', [address]);
};

/**
* 解除蓝牙设备链接

* @param successCallback:success message
* @param failureCallback:error message
* @param address:设备物理地址
*/
Bluetooth.prototype.disconnect = function(successCallback, failureCallback, address) {
  return cordova.exec(successCallback, failureCallback, 'BluetoothPlugin', 'disconnect', [address]);
};

/**
* 往蓝牙设备写字符串数据

* @param successCallback:success message
* @param failureCallback:error message
* @param address:设备物理地址
* @param message:要写入的数据
* @param encoding:数据编码格式
*/
Bluetooth.prototype.writeString = function(successCallback, failureCallback, address, message, encoding) {
  return cordova.exec(successCallback, failureCallback, 'BluetoothPlugin', 'writeString', [address,message,encoding]);
};

/**
* 往蓝牙设备写ASCII码数据

* @param address:设备物理地址
* @param ascii:要写入的ASCII码数据
*/
Bluetooth.prototype.writeASCII = function(address, ascii) {
  return cordova.exec(function(message) {
    //alert(message);
  }, 
  function(error) {
    // alert( 'Error: ' + error );
  },'BluetoothPlugin', 'writeASCII', [address,ascii]);
};

if(!window.plugins) {
  window.plugins = {};
}
if (!window.plugins.BluetoothPlugin) {
  window.plugins.BluetoothPlugin = new Bluetooth();
}

----------------------------------------------------------------------

后台BluetoothPlugin.java

/*
Copyright  2013.01 101.key

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package org.apache.cordova.plugin;

import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import org.apache.cordova.api.CallbackContext;
import org.apache.cordova.api.CordovaPlugin;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.util.Log;

public class BluetoothPlugin extends CordovaPlugin {

private static final String ACTION_IS_BT_ENABLED = "isBTEnabled"; // 蓝牙是否可用
private static final String ACTION_ENABLE_BT = "enableBT"; // 启用蓝牙
private static final String ACTION_DISABLE_BT = "disableBT"; // 禁用蓝牙
private static final String ACTION_DISCOVERDEVICES = "discoverDevices"; // 搜索蓝牙设备
private static final String ACTION_STOP_DISCOVERDEVICES = "stopDiscoverDevices"; // 停止蓝牙设备搜索

private static final String ACTION_IS_BOUND_BT = "isBoundBT"; // 指定的蓝牙设备是否绑定
private static final String ACTION_BOUND_BT = "boundBT"; // 绑定蓝牙设备
private static final String ACTION_UNBOUND_BT = "unBoundBT"; // 解除蓝牙设备绑定
private static final String ACTION_LIST_BOUND_DEVICES = "listBoundDevices"; // 列出所有已绑定的蓝牙设备

private static final String ACTION_IS_CONNECT = "isConnect"; // 指定的蓝牙设备是否已链接
private static final String ACTION_CONNECT = "connect"; // 链接蓝牙设备
private static final String ACTION_DISCONNECT = "disconnect"; // 断开蓝牙设备链接

private static final String ACTION_WRITE_STRING = "writeString"; // 往蓝牙设备写入字符串数据
private static final String ACTION_WRITE_ASCII = "writeASCII"; // 往蓝牙设备写入ASCII码数据

private BluetoothAdapter m_bluetoothAdapter = null; // 蓝牙适配器
private BPBroadcastReceiver m_bpBroadcastReceiver = null; // 广播状态接收者
private boolean m_discovering = false; // 是否正在搜索蓝牙
private boolean m_stateChanging = false; // 状态变化
private JSONArray m_discoveredDevices = null; //已发现的蓝牙设备
private JSONArray m_boundDevices = null; //已绑定的蓝牙设备
private Map bluetoothSocketMap = new HashMap(); //已链接的蓝牙设备socket映射(address to socket)

/**
* Constructor for Bluetooth plugin
*/
public BluetoothPlugin() {
  m_bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
  m_bpBroadcastReceiver = new BPBroadcastReceiver();
}

/**
* Execute a bluetooth function
*/
@Override
public boolean execute(String action, JSONArray args,
final CallbackContext callbackContext) throws JSONException {
// Register for necessary bluetooth events
Log.d("BluetoothPlugin", "Action: " + action);

// Check if bluetooth is supported at all
if (m_bluetoothAdapter == null) {
callbackContext.error("No bluetooth adapter found");
return false;
} else {
if (ACTION_IS_BT_ENABLED.equals(action)) {
try {
boolean isEnabled = m_bluetoothAdapter.isEnabled();
callbackContext.success(isEnabled + "");
} catch (Exception Ex) {
Log.d("BluetoothPlugin", "Got Exception " + Ex.getMessage());
callbackContext.error(Ex.getMessage());
}

} else if (ACTION_ENABLE_BT.equals(action)) {
if (!m_bluetoothAdapter.isEnabled()) {
m_stateChanging = true;
cordova.startActivityForResult(this, new Intent(
BluetoothAdapter.ACTION_REQUEST_ENABLE), 1);
while (m_stateChanging) {
}
;
}
if (m_bluetoothAdapter.isEnabled()) {
callbackContext.success("true");
} else {
callbackContext.error("蓝牙设备启用失败!");
return false;
}
}
else if (ACTION_DISABLE_BT.equals(action)) {
if (!m_bluetoothAdapter.disable()
&& m_bluetoothAdapter.isEnabled()) {
callbackContext.error("蓝牙设备禁用失败!");
return false;
} else {
callbackContext.success("true");
}
} else if (ACTION_DISCOVERDEVICES.equals(action)) {
cordova.getActivity().registerReceiver(m_bpBroadcastReceiver,
new IntentFilter(BluetoothDevice.ACTION_FOUND));
cordova.getActivity().registerReceiver(
m_bpBroadcastReceiver,
new IntentFilter(
BluetoothAdapter.ACTION_DISCOVERY_STARTED));
cordova.getActivity().registerReceiver(
m_bpBroadcastReceiver,
new IntentFilter(
BluetoothAdapter.ACTION_DISCOVERY_FINISHED));
cordova.getThreadPool().execute(new Runnable() {
public void run() {
m_discoveredDevices = new JSONArray();
if (m_bluetoothAdapter.isDiscovering()) {
m_bluetoothAdapter.cancelDiscovery();
}
if (!m_bluetoothAdapter.startDiscovery()) {
callbackContext.error("无法启动蓝牙搜索!");
} else {
Log.i("BluetoothPlugin", "Discovering devices...");
m_discovering = true;
// Wait for discovery to finish
while (m_discovering) {
}
Log.d("BluetoothPlugin", "DiscoveredDevices: "
+ m_discoveredDevices.length());
callbackContext.success(m_discoveredDevices);
}
}
});
} else if (ACTION_STOP_DISCOVERDEVICES.equals(action)) {
try {
boolean stopped = true;
Log.d("BluetoothPlugin",
"Stop Discovering Bluetooth Devices...");
if (m_bluetoothAdapter.isDiscovering()) {
Log.i("BluetoothPlugin", "Stop discovery...");
stopped = m_bluetoothAdapter.cancelDiscovery();
m_discovering = false;
}
callbackContext.success(stopped + "");
} catch (Exception Ex) {
Log.d("BluetoothPlugin", "Got Exception " + Ex.getMessage());
callbackContext.error(Ex.getMessage());
}
}
else if (ACTION_IS_BOUND_BT.equals(action)) {
try {
String addressDevice = args.getString(0);
BluetoothDevice device = m_bluetoothAdapter.getRemoteDevice(addressDevice);
boolean state = false;
if (device != null && device.getBondState() == BluetoothDevice.BOND_BONDED)
state = true;
else
state = false;
Log.d("BluetoothPlugin", device.getName() + "["
+ device.getAddress() + "]isBound: " + state);
callbackContext.success(state + "");
} catch (Exception Ex) {
Log.d("BluetoothPlugin", ACTION_IS_BOUND_BT
+ " Got Exception " + Ex.getMessage());
callbackContext.error(Ex.getMessage());
}
}
else if (ACTION_BOUND_BT.equals(action)) {
try {
String addressDevice = args.getString(0);
if (m_bluetoothAdapter.isDiscovering()) {
m_bluetoothAdapter.cancelDiscovery();
}
boolean paired = false;
BluetoothDevice device = m_bluetoothAdapter.getRemoteDevice(addressDevice);
if (device != null && device.getBondState() == BluetoothDevice.BOND_BONDED){
paired = true;
callbackContext.success(paired + "");
return true;
}
Log.d("BluetoothPlugin",
"start createBond with Bluetooth device with name "
+ device.getName() + " and address "
+ device.getAddress());
Method m = device.getClass().getMethod("createBond");
paired = (Boolean) m.invoke(device);
Log.d("BluetoothPlugin", "Returning " + "Result: " + paired);
callbackContext.success(paired + "");
} catch (Exception Ex) {
Log.d("BluetoothPlugin", "Got Exception " + Ex.getMessage());
callbackContext.error(Ex.getMessage());
}
} else if (ACTION_UNBOUND_BT.equals(action)) {
try {
String addressDevice = args.getString(0);
if (m_bluetoothAdapter.isDiscovering()) {
m_bluetoothAdapter.cancelDiscovery();
}
BluetoothDevice device = m_bluetoothAdapter
.getRemoteDevice(addressDevice);
boolean unpaired = false;
Log.d("BluetoothPlugin",
"unBouding Bluetooth device with "
+ device.getName() + " and address "
+ device.getAddress());
Method m = device.getClass().getMethod("removeBond");
unpaired = (Boolean) m.invoke(device);
Log.d("BluetoothPlugin", ACTION_UNBOUND_BT + " Returning "
+ "Result: " + unpaired);
callbackContext.success(unpaired + "");
} catch (Exception Ex) {
Log.d("BluetoothPlugin", ACTION_UNBOUND_BT
+ " Got Exception " + Ex.getMessage());
callbackContext.error(Ex.getMessage());
}
} else if (ACTION_LIST_BOUND_DEVICES.equals(action)) {
try {
Log.d("BluetoothPlugin", "Getting paired devices...");
m_boundDevices = new JSONArray();
Set<BluetoothDevice> pairedDevices = m_bluetoothAdapter
.getBondedDevices();
if (pairedDevices.size() > 0) {
for (BluetoothDevice device : pairedDevices) {
Log.i("BluetoothPlugin",
device.getName() + " "
+ device.getAddress() + " "
+ device.getBondState());

if ((device.getName() != null)
&& (device.getBluetoothClass() != null)) {
try {
JSONObject deviceInfo = new JSONObject();
deviceInfo.put("name", device.getName());
deviceInfo.put("address",
device.getAddress());
m_boundDevices.put(deviceInfo);
} catch (JSONException e) {
Log.e("BluetoothPlugin", e.getMessage());
}

} else
Log.i("BluetoothPlugin",device.getName()
+ " Problems retrieving attributes. Device not added ");
}
}
Log.d("BluetoothPlugin", ACTION_LIST_BOUND_DEVICES
+ " Returning " + m_boundDevices.toString());
callbackContext.success(m_boundDevices);
} catch (Exception Ex) {
Log.d("BluetoothPlugin", ACTION_LIST_BOUND_DEVICES
+ " Got Exception " + Ex.getMessage());
callbackContext.error(Ex.getMessage());
}

else if (ACTION_IS_CONNECT.equals(action)) {
String addressDevice = args.getString(0);
if (bluetoothSocketMap.containsKey(addressDevice)){
callbackContext.success("true");
}else{
Log.d("BluetoothPlugin", "设备未链接!");
callbackContext.error("设备未链接!");

}
else if (ACTION_CONNECT.equals(action)) {
try {
String addressDevice = args.getString(0);
if (bluetoothSocketMap.containsKey(addressDevice)){
Log.d("BluetoothPlugin", "该设备已链接,不再重新进行链接");
callbackContext.success("该设备已链接!");
return true;
}
Log.d("BluetoothPlugin", "Connecting...");
BluetoothDevice bluetoothDevice = m_bluetoothAdapter
.getRemoteDevice(addressDevice);

Method m = bluetoothDevice.getClass().getMethod(
"createRfcommSocket", new Class[] { int.class });
BluetoothSocket bluetoothSocket = (BluetoothSocket) m.invoke(
bluetoothDevice, 1);
try {
bluetoothSocket.connect();
} catch (IOException e) {
Log.d("BluetoothPlugin",
"connect fail: " + e.getMessage());
callbackContext.error("设备链接失败: " + e.getMessage());
return false;
}
bluetoothSocketMap.put(addressDevice, bluetoothSocket);
Log.d("BluetoothPlugin", addressDevice+ " 设备链接成功");
callbackContext.success("设备链接成功!");
} catch (Exception e) {
Log.e("BluetoothPlugin",
e.toString() + " / " + e.getMessage());
callbackContext.error("链接失败: " + e.getMessage());
}
} else if (ACTION_DISCONNECT.equals(action)) {
String addressDevice = args.getString(0);
if (bluetoothSocketMap.containsKey(addressDevice)){
BluetoothSocket bluetoothSocket = (BluetoothSocket)bluetoothSocketMap.get(addressDevice);
Log.d("BluetoothPlugin", addressDevice+"断开链接操作中...");
try {
bluetoothSocket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
Log.e("BluetoothPlugin",
e.toString() + " / " + e.getMessage());
callbackContext.error("断开链接失败: " + e.getMessage());
return false;
}
bluetoothSocketMap.remove(addressDevice);
bluetoothSocket = null;
Log.d("BluetoothPlugin", addressDevice+"已成功断开链接");
callbackContext.success("已成功解除设备链接!");
}else{
Log.d("BluetoothPlugin", addressDevice+" 设备无可用链接可断开,请重新确认!");
callbackContext.success("该设备无可用链接可断开,请重新确认!");
}
} else if (ACTION_WRITE_STRING.equals(action)) {
if (m_bluetoothAdapter.isDiscovering()) {
m_bluetoothAdapter.cancelDiscovery();
}
try {
String addressDevice = args.getString(0);
final String message = args.getString(1);
final String encoding = args.getString(2);
if (!isReady(callbackContext, addressDevice)){
return false;
}
BluetoothSocket bluetoothSocket = (BluetoothSocket)bluetoothSocketMap.get(addressDevice);
Log.d("BluetoothPlugin", "开始写入数据:"+message);
OutputStream outputStream = bluetoothSocket
.getOutputStream();
byte[] bytes = message.getBytes(encoding);
outputStream.write(bytes);
Log.d("BluetoothPlugin", "写入数据成功");
callbackContext.success(message);

} catch (Exception Ex) {
Log.d("BluetoothPlugin", ACTION_WRITE_STRING
+ " Got Exception " + Ex.getMessage());
callbackContext.error(Ex.getMessage());

} else if (ACTION_WRITE_ASCII.equals(action)) {
if (m_bluetoothAdapter.isDiscovering()) {
m_bluetoothAdapter.cancelDiscovery();
}
try {
String addressDevice = args.getString(0);
final String ascii = args.getString(1);

if (!isReady(callbackContext, addressDevice)){
return false;
}

BluetoothSocket bluetoothSocket = (BluetoothSocket)bluetoothSocketMap.get(addressDevice);

Log.d("BluetoothPlugin", "开始写入数据:"+ascii);
OutputStream outputStream = bluetoothSocket
.getOutputStream();
byte[] bytes = toASCII(ascii);
outputStream.write(bytes);

Log.d("BluetoothPlugin", "写入数据成功");
callbackContext.success(ascii);
} catch (Exception Ex) {
Log.d("BluetoothPlugin", ACTION_WRITE_ASCII
+ " Got Exception " + Ex.getMessage());
callbackContext.error(Ex.getMessage());

}else {
callbackContext.error("Action '" + action + "' not supported");
return false;
}
}
return true;
}

public void setDiscovering(boolean state) {
m_discovering = state;
}

/**
* Receives activity results
*/
@Override
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
if (requestCode == 1) {
m_stateChanging = false;
}
}

@Override
public void onDestroy() {
// TODO Auto-generated method stub
Log.i("BluetoothPlugin", "onDestroy " + this.getClass());
cordova.getActivity().unregisterReceiver(m_bpBroadcastReceiver);
super.onDestroy();
}

/**
* Helper class for handling all bluetooth based events
*/
private class BPBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.d("BluetoothPlugin", "Action: " + action);
// Check if we found a new device
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
BluetoothDevice bluetoothDevice = intent
.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
try {
JSONObject deviceInfo = new JSONObject();
if (bluetoothDevice.getBondState() == BluetoothDevice.BOND_BONDED) {
deviceInfo.put("name", bluetoothDevice.getName()
+ "(已绑定)");
} else {
deviceInfo.put("name", bluetoothDevice.getName());
}
deviceInfo.put("address", bluetoothDevice.getAddress());
m_discoveredDevices.put(deviceInfo);
Log.i("BluetoothPlugin",
"Device[" + bluetoothDevice.getName() + " "
+ bluetoothDevice.getAddress()
+ "] add to discoveredDevices");
} catch (JSONException e) {
Log.e("BluetoothPlugin", e.getMessage());
}
} else if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)) {
Log.i("BluetoothPlugin", "Discovery started");
setDiscovering(true);
}
// Check if we finished discovering devices
else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
Log.i("BluetoothPlugin", "Discovery finished");
setDiscovering(false);
}
}
};

/**
* 开始写数据前,相关前置条件是否准备好
* @param callbackContext
* @param addressDevice
* @return
*/
private boolean isReady(CallbackContext callbackContext, String addressDevice){
if (!m_bluetoothAdapter.isEnabled()){
Log.d("BluetoothPlugin", "m_bluetoothAdapter isEnabled 不可用,无法写入.");
callbackContext.error("蓝牙适配器暂不能用,无法写入数据!");
return false;
}

BluetoothDevice bluetoothDevice = m_bluetoothAdapter
.getRemoteDevice(addressDevice);

if (bluetoothDevice == null){//找不到设备
Log.d("BluetoothPlugin", "系统找不到蓝牙设备,无法写入.");
callbackContext.error("系统找不到蓝牙设备,无法写入数据!");
return false;
}

if (bluetoothDevice.getBondState() != BluetoothDevice.BOND_BONDED){//已绑定链接
Log.d("BluetoothPlugin", "该设备未绑定,无法写入.");
callbackContext.error("该设备未绑定,无法写入数据!");
return false;
}

if (!bluetoothSocketMap.containsKey(addressDevice)){
Log.d("BluetoothPlugin", "该设备未链接,无法写入.");
callbackContext.error("该设备未链接,无法写入数据!");
return false;
}

return true;
}

private byte[] toASCII(String ascii) {
try {
String[] as = ascii.split(",");
byte[] bytes = new byte[as.length];
for (int i = 0; i < as.length; i++) {
bytes[i] = (byte) Integer.parseInt(as[i]);
}
return bytes;
} catch (Exception e) {
Log.d("BluetoothPlugin", "Invalid ASCII code.");
return null;
}
}

}

--------------------------------------------------------

页面调用

function writeString() {
window.plugins.BluetoothPlugin.writeASCII(
'设备MAC地址',
'27,64'  //蓝牙打印设备状态重置、初始化
);
window.plugins.BluetoothPlugin.writeString(
function(message) {
alert(message);
}, 
function(error) {
alert( 'Error: ' + error );
},
'设备MAC地址',
$('#msg').val(),
'GBK'
);
window.plugins.BluetoothPlugin.writeASCII(
'设备MAC地址',
'10,10,10,10' //换行打印
);
}

原文地址:https://www.cnblogs.com/leiyangs/p/6093978.html