浅谈BLE

    最近刚开始接触Android,Android编程对于一个学过C++的人来说,入门挺容易的;但想要做一名合格的Android开发工程师还有很长的路要走。当然这里仅限于我C++也不是学的很好,也只能说是个入门级别,大牛除外,大牛级别的人学什么编程语言都很快。
    说说BLE的特性吧。蓝牙4.0最重要的特性是省电,极低的运行和待机功耗可以使一粒纽扣电池连续工作数年之久。可以用于计步器、心律监视器、智能仪表、传感器物联网等众多领域。BLE通信由三部分Service、Characteristic、Descriptor构成,这三部分都由UUID作为唯一标示符。一个蓝牙4.0的终端可以包含多个Service,一个Service可以包含多个Characteristic,一个Characteristic包含一个Value和多个Descriptor,一个Descriptor包含一个Value。接下来说说gatt回调函数9个要实现的方法。
    private BluetoothGattCallback GattCallback = new BluetoothGattCallback() {
    // 这里有9个要实现的方法,看情况要实现那些,用到那些就实现那些
    public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState){};
    public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status){};
};

BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
BluetoothGatt gatt = device.connectGatt(this, false, mGattCallback);

:notification对应onCharacteristicChanged;
 
gatt.setCharacteristicNotification(characteristic, true);
:readCharacteristic对应onCharacteristicRead;
 
gatt.readCharacteristic(characteristic);
: writeCharacteristic对应onCharacteristicWrite;
 
gatt.wirteCharacteristic(mCurrentcharacteristic);
:连接蓝牙或者断开蓝牙 对应 onConnectionStateChange;
 
:readDescriptor对应onDescriptorRead;
 
:writeDescriptor对应onDescriptorWrite;
 
gatt.writeDescriptor(descriptor);
:readRemoteRssi对应onReadRemoteRssi;
 
gatt.readRemoteRssi()
:executeReliableWrite对应onReliableWriteCompleted;
:discoverServices对应onServicesDiscovered。

代码实现:
    实现步骤:1、开启蓝牙
              2、扫描蓝牙
              3、与外设建立gatt连接
              4、枚举服务以及对应的UUID号
              5、断开连接
    具体代码:
        MainActivity.java
package com.example.ble;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
import android.widget.Toast;

/**
 * @date 2015-07-31
 * @describe 
 * @author lai
 *
 */
@SuppressLint("NewApi")
public class MainActivity extends Activity {
private static Context mContext;// 上下文
private static final String TAG = MainActivity.class.getSimpleName();// 标志

private SharedPreferences sp = null;

private BluetoothAdapter mBluetoothAdapter = null;// 本地蓝牙设备

private Handler mHandler = null;// 用于postDelay
private boolean mScanning = false;// 循环标志位
private static final long SCAN_PERIOD = 10000;// 扫描10s
private static final int REQUEST_ENABLE_BT = 1;// 请求码

private ListView mListView = null;
private TestAdapter mAdapter = null;

@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
if (!checkBluetooth()) {
finish();
}
init();
		
}

@Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
System.out.println("2");
// 为了确保设备上蓝牙能使用, 如果当前蓝牙设备没启用,弹出对话框向用户要求授予权限来启用
		if (!mBluetoothAdapter.isEnabled()) {
			if (!mBluetoothAdapter.isEnabled()) {
				Intent enableBtIntent = new Intent(
						BluetoothAdapter.ACTION_REQUEST_ENABLE);
				startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
			}
		}
		mAdapter = new TestAdapter(mContext);
		mListView.setAdapter(mAdapter);
		if (mBluetoothAdapter.isEnabled()) {
			scanLeDevice(true);

		}
	}

	@Override
	protected void onPause() {

		super.onPause();
		scanLeDevice(false);
		mAdapter.clear();
		System.out.println("4");
	}

	@Override
	protected void onDestroy() {
		// TODO Auto-generated method stub
		super.onDestroy();
		suiside();
	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		// TODO Auto-generated method stub
		if (requestCode == REQUEST_ENABLE_BT
				&& resultCode == Activity.RESULT_CANCELED) {
			finish();
			return;
		}
		super.onActivityResult(requestCode, resultCode, data);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		getMenuInflater().inflate(R.menu.main, menu);
		if (!mScanning) {
			menu.findItem(R.id.menu_stop).setVisible(false);
			menu.findItem(R.id.menu_scan).setVisible(true);
			menu.findItem(R.id.menu_refresh).setActionView(null);
		} else {
			menu.findItem(R.id.menu_stop).setVisible(true);
			menu.findItem(R.id.menu_scan).setVisible(false);
			menu.findItem(R.id.menu_refresh)
					.setActionView(R.layout.menurefresh);
		}
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case R.id.menu_scan:
			mAdapter.clear();
			scanLeDevice(true);

			break;
		case R.id.menu_stop:
			scanLeDevice(false);
			break;
		}
		return true;
	}

	/**
	 * 判断是否支持蓝牙和BLE
	 * 
	 * @return
	 */
	private boolean checkBluetooth() {
		// 判断是否支持BLE
		if (!getPackageManager().hasSystemFeature(
				PackageManager.FEATURE_BLUETOOTH_LE)) {
			toast("ble not supported");
			return false;
		}

		// 初始化BluetoothAdapter
		final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
		mBluetoothAdapter = bluetoothManager.getAdapter();

		// 检查设备上是否支持蓝牙不支 持就退出程序
		if (mBluetoothAdapter == null) {
			toast("bluetooth not supported");
			return false;
		}

		return true;
	}

	/**
	 * 初始化数据
	 */
	private void init() {
		mContext = this;
		mHandler = new Handler();
		sp = getSharedPreferences(Constant.SP_NAME, Context.MODE_PRIVATE);
		mListView = (ListView) findViewById(R.id.list_view);
		mListView.setOnItemClickListener(mItemClickListener);
		System.out.println("1");
	}

	/**
	 * 列表单击事件
	 */
	private OnItemClickListener mItemClickListener = new OnItemClickListener() {

		@Override
		public void onItemClick(AdapterView<?> arg0, View arg1, int position,
				long arg3) {
			// TODO Auto-generated method stub
			/**
			 * 跳转到BLEService 传递一个参数 一个地址 并把名字和地址保存起来
			 */
			System.out.println("3");
			BluetoothDevice mDevice = mAdapter.getDevice(position);
			toast(mDevice.getAddress());
			saveDeviceAddress(mDevice.getAddress());
			startTheService();

		}
	};

	/**
	 * 启动BLE通信服务
	 */
	private void startTheService() {
		Intent service = new Intent();
		service.setClass(mContext, BLEService.class);
		startService(service);
	}

	/**
	 * 把地址保存起来 以便服务可以使用
	 * 
	 * @param address
	 */
	private void saveDeviceAddress(String address) {
		Editor editor = sp.edit();
		editor.putString(Constant.KEY_DEVICE_ADDRESS, address);
		editor.commit();
	}

	/**
	 * 吐丝
	 * 
	 * @param text
	 */
	private void toast(String text) {
		Toast.makeText(mContext, text, Toast.LENGTH_SHORT).show();
	}

	/**
	 * 扫描BLE设备
	 * 
	 * @param enable
	 */
	private void scanLeDevice(final boolean enable) {
		if (enable) {
			mHandler.postDelayed(new Runnable() {
				@Override
				public void run() {
					mScanning = false;
					mBluetoothAdapter.stopLeScan(mLeScanCallback);
					invalidateOptionsMenu();
				}
			}, SCAN_PERIOD);

			mScanning = true;
			mBluetoothAdapter.startLeScan(mLeScanCallback);
		} else {
			mScanning = false;
			mBluetoothAdapter.stopLeScan(mLeScanCallback);
		}
		invalidateOptionsMenu();
	}

	/**
	 * BLE扫描回调函数,设备保存在remoteDevice里面
	 */
	private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {

		@Override
		public void onLeScan(final BluetoothDevice device, int rssi,
				byte[] scanRecord) {
			// TODO Auto-generated method stub
			runOnUiThread(new Runnable() {
				@Override
				public void run() {
					mAdapter.addDevice(device);
					mAdapter.notifyDataSetChanged();
				}
			});
		}
	};

	/**
	 * 自杀
	 */
	private void suiside() {
		scanLeDevice(false);
		sp = null;
	}
}
  
TestAdapter.java

package com.example.ble;
import java.util.ArrayList;


import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;


public class TestAdapter extends BaseAdapter {
	private ArrayList<BluetoothDevice> mLeDevices;
	private LayoutInflater mInflater;
	
	public TestAdapter(Context context) {
		mLeDevices = new ArrayList<BluetoothDevice>();
		mInflater = LayoutInflater.from(context);
	}


	@Override
	public int getCount() {
		// TODO Auto-generated method stub
		return mLeDevices.size();
	}


	@Override
	public Object getItem(int arg0) {
		// TODO Auto-generated method stub
		if (mLeDevices.size() <= arg0) {
			return null;}
		return mLeDevices.get(arg0);
	}


	@Override
	public long getItemId(int arg0) {
		// TODO Auto-generated method stub
		return arg0;
	}


	@Override
	public View getView(int position, View view, ViewGroup arg2) {
		// TODO Auto-generated method stub
		ViewHolder viewHolder;
		if (null == view) {
			viewHolder = new ViewHolder();


			view = mInflater.inflate(R.layout.item_ble, null);
			viewHolder.deviceName = (TextView) view
					.findViewById(R.id.device_name);


			view.setTag(viewHolder);
		} else {
			viewHolder = (ViewHolder) view.getTag();
		}


		BluetoothDevice device = mLeDevices.get(position);


		final String deviceName = device.getName();
		if (deviceName != null && deviceName.length() > 0)
			viewHolder.deviceName.setText(deviceName);
		else
			viewHolder.deviceName.setText("unknown name");


		return view;
	}


	private class ViewHolder {
		public TextView deviceName;


	}
	
	/**
	 * 设置数据源
		 * @param mDevices
	 */
	public void setData(ArrayList<BluetoothDevice> mDevices) {
		this.mLeDevices = mDevices;


	}


	/**
	 * 添加设备
		 * @param mDevice
	 */
	public void addDevice(BluetoothDevice mDevice) {


		if (!mLeDevices.contains(mDevice)) {
			mLeDevices.add(mDevice);
		}
	}


	/**
	 * 得到设备
		 * @param position
	 * @return
	 */
	public BluetoothDevice getDevice(int position) {


		if (mLeDevices.size() <= position) {
			return null;
		}
		return mLeDevices.get(position);
	}


	/**
	 * 清空设备
	 */
	public void clear() {


		mLeDevices.clear();
	}
}

BLEService.java

package com.example.ble;
import java.util.List;
import android.annotation.SuppressLint;
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.IBinder;
import android.util.Log;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;


public class BLEService extends Service {

private static byte[] testData = { 1, 2, 3 };
private static Context mContext;// 上下文
private static final String TAG = BLEService.class.getSimpleName();// TAG
private BluetoothManager mBluetoothManager = null;// 蓝牙管理器
private BluetoothAdapter mBluetoothAdapter = null;// 本地设备
private String mBluetoothDeviceAddress = null;// 远程设备地址
private BluetoothGatt mBluetoothGatt = null;// GATT通信
private BluetoothGattCharacteristic mCharacteristic = null;// 可读写可通知的
private SharedPreferences sp = null;
private static final boolean AUTO_CONNECT = true;// 是否自动连接
private static final boolean NOTIFICATION_ENABLED = true;
private int mConnectionState = STATE_DISCONNECTED;// 连接状态
private static final int STATE_DISCONNECTED = 0;// 断开连接
private static final int STATE_CONNECTING = 1;// 连接中
private static final int STATE_CONNECTED = 2;// 已连接
@Override
public IBinder onBind(Intent arg0) {
	// TODO Auto-generated method stub
return null;
}

@Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
init();
}


@Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
suiside();
}


	@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
// 如果地址不为空就尝试连接 如果为空就跳到BLEActivity让用户去选择BLE设备
if (mBluetoothDeviceAddress != null) {
       if (connect(mBluetoothDeviceAddress)) {
System.out.println("mBluetoothDeviceAddress");			
	} else {
		}
} else {
Intent bleIntent = new Intent();
bleIntent.setClass(mContext, MainActivity.class);
bleIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(bleIntent);
	}
// return super.onStartCommand(intent, flags, startId);
return Service.START_STICKY;
}


	/**
	 * 各种初始化信息
	 */
private void init() {
mContext = this;
if (!initBluetooth()) {
	stopSelf();
	}
sp = getSharedPreferences(Constant.SP_NAME, Context.MODE_PRIVATE);
mBluetoothDeviceAddress = sp.getString(Constant.KEY_DEVICE_ADDRESS,null);
	}
	
private void toast(String text) {
Toast.makeText(mContext, text, Toast.LENGTH_SHORT).show();
}
	/**
	 * 初始化BluetoothManager和BluetoothAdapter
		 * @return
	 */
private boolean initBluetooth() {
if (mBluetoothManager == null) {
mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
if (mBluetoothManager == null) {
	return false;
	}
}
mBluetoothAdapter = mBluetoothManager.getAdapter();
if (mBluetoothAdapter == null) {
	return false;
	}
return true;
}


	/**
	 * 自殺
	 */
private void suiside() {
disconnect();
close();
try {
	if (mBluetoothAdapter != null) {
	mBluetoothAdapter.disable();
	mBluetoothAdapter = null;
	mBluetoothManager = null;
	sp = null;
}
		} catch (Exception e) {
			toast("关闭蓝牙失败,请手动关闭");
		}
	}


	/**
	 * 关闭通信
	 */
private void close() {
if (mBluetoothGatt == null) {
	return;
	}
mBluetoothGatt.close();
mBluetoothGatt = null;
	}


	/**
	 * 建立通信連接
		 * @param address
	 * @return
	 */
private boolean connect(final String address) {
if (mBluetoothAdapter == null || address == null) {
	return false;
}


if (mBluetoothDeviceAddress != null
	&& address.equals(mBluetoothDeviceAddress)
	&& mBluetoothGatt != null) {
if (mBluetoothGatt.connect()) {
	mConnectionState = STATE_CONNECTING;
	return true;
} else {
	return false;
		}
	}
final BluetoothDevice device = mBluetoothAdapter
	.getRemoteDevice(address);
if (device == null) {
	return false;
		}
mBluetoothGatt = device.connectGatt(this, AUTO_CONNECT, mGattCallback);
System.out.println("mBluetoothGatt");
mBluetoothDeviceAddress = address;
	
mConnectionState = STATE_CONNECTING;
return true;
	}


	/**
	 * 斷開GATT連接
	 */
private void disconnect() {
System.out.println("e");
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
	return;
	}
mBluetoothGatt.disconnect();
}


	/**
	 * GATT通信回調函數
	 */
@SuppressLint("NewApi")
private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {


		@Override
		
public void onCharacteristicChanged(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic) {
	// TODO Auto-generated method stub
	// super.onCharacteristicChanged(gatt, characteristic);
System.out.println("我收到的:" + new String(characteristic.getValue()));
	}


		@Override
public void onCharacteristicRead(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic, int status) {
// TODO Auto-generated method stub
super.onCharacteristicRead(gatt, characteristic, status);
	}


		@Override
public void onCharacteristicWrite(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic, int status) {
// TODO Auto-generated method stub
super.onCharacteristicWrite(gatt, characteristic, status);
	}


		@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status,
	int newState) {
// TODO Auto-generated method stub
// super.onConnectionStateChange(gatt, status, newState);
if (newState == BluetoothProfile.STATE_CONNECTED) {
if (mBluetoothGatt != null)
mBluetoothGatt.discoverServices();
mConnectionState = STATE_CONNECTED;
System.out.println("state connected");
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
	// connect(mBluetoothDeviceAddress);
mConnectionState = STATE_DISCONNECTED;
System.out.println("state disconnected");
		}
	}


		@Override
public void onDescriptorRead(BluetoothGatt gatt,
BluetoothGattDescriptor descriptor, int status) {
// TODO Auto-generated method stub
super.onDescriptorRead(gatt, descriptor, status);
		}


		@Override
public void onDescriptorWrite(BluetoothGatt gatt,
BluetoothGattDescriptor descriptor, int status) {
// TODO Auto-generated method stub
super.onDescriptorWrite(gatt, descriptor, status);
		}


		@Override
public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
// TODO Auto-generated method stub
super.onReadRemoteRssi(gatt, rssi, status);
		}


		@Override
public void onReliableWriteCompleted(BluetoothGatt gatt, int status) {
// TODO Auto-generated method stub
	super.onReliableWriteCompleted(gatt, status);
		}


		@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
// TODO Auto-generated method stub
// super.onServicesDiscovered(gatt, status);		
if (status == BluetoothGatt.GATT_SUCCESS) {
if (mBluetoothGatt != null) {
BluetoothGattService mGattService = mBluetoothGatt
	.getService(SampleGattAttributes.UUID_SERVICE);
System.out.println("0");
		
mCharacteristic = mGattService
	.getCharacteristic(SampleGattAttributes.UUID_CHARACTERISTIC);
		
List<BluetoothGattDescriptor> mDescriptors = mCharacteristic.getDescriptors();
for (BluetoothGattDescriptor mDescriptor : mDescriptors) {
	System.out.println(mDescriptor.getUuid().toString());
			}
	setCharacteristicNotification(mCharacteristic,NOTIFICATION_ENABLED);
	wirteToBLE(testData);
	System.out.println(new String(readFromBLE()));
	wirteToBLE(testData);
	System.out.println(new String(readFromBLE()));
		}
		}
		}
		};
	
	/**
	 * 设置后可以使用通知 设备给手机发送通知时可触发onCharacteristicChanged()
		 * @param characteristic
	 * @param enabled
	 */
private void setCharacteristicNotification(
BluetoothGattCharacteristic characteristic, boolean enabled) {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
System.out.println("setCharacteristicNotification");
return;
  }
mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
BluetoothGattDescriptor descriptor = characteristic
.getDescriptor(SampleGattAttributes.UUID_DESCRIPTOR);
if (descriptor != null) {
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
mBluetoothGatt.writeDescriptor(descriptor);
		}
	}
	
	/**
	 * 获取此实例
		 * @return
	 */
public static BLEService self() {
	if (mContext != null)
	return (BLEService) mContext;
	return null;
	}

        /**
	 * 通信接口 通过此函数即可向BLE设备写入数据
		 * @param value
	 * @return
	 */
public boolean wirteToBLE(byte[] value) {
System.out.println("f");
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
	Log.w(TAG, "BluetoothAdapter not initialized");
	return false;
		}
mCharacteristic.setValue(value);
boolean isSuccess = mBluetoothGatt.writeCharacteristic(mCharacteristic);
return isSuccess;
	}
	/**
	 * 通信接口 从BLE设备读数据
		 * @return
	 */
public byte[] readFromBLE() {
	byte[] value = null;
	System.out.println("g");
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
			return null;
		}
boolean isSuccess = mBluetoothGatt.readCharacteristic(mCharacteristic);
if (isSuccess) {
value = mCharacteristic.getValue();
		}
return value;
	}           
          //-----Characteristics的字段信息-----//        
}

item_ble.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >


<TextView
        android:id="@+id/device_name"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="yuuyy88" 
        android:textSize="22sp"/>
</LinearLayout>

main.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" > 
  <ListView
        android:id="@+id/list_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
    </ListView>
 /FrameLayout>

meumrefresh.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    android:layout_height="wrap_content"  
    android:layout_width="56dp"  
    android:minWidth="56dp">  
   
    <ProgressBar android:layout_width="32dp"  
        android:layout_height="32dp"  
        android:layout_gravity="center"  
        style="?indeterminateProgressStyle" />  
</FrameLayout> 
main.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context="com.example.ble.MainActivity" >


   
    <item android:id="@+id/menu_scan" 
        android:title="扫描" 
        android:layout_width="fill_parent"    
        android:layout_height="fill_parent" 
        />    
  
    <item android:id="@+id/menu_stop" 
        android:title="扫描停止" 
        android:layout_width="fill_parent"    
        android:layout_height="fill_parent" 
        />
        
    <item android:id="@+id/menu_refresh" 
        android:title="刷新扫描" 
        android:layout_width="fill_parent"    
        android:layout_height="fill_parent" 
        />
    
</menu>

    至此大部分代码已完成,还有部分定义常量的代码自行添加。还有请自行枚举出服务的UUID号然后添加到对应的代码中,否则程序会有问题。
    
    本文的思想方法来自于http://blog.youkuaiyun.com/zhaicaixiansheng/article/details/47070187;代码也主要来自于这篇博客;本文只是将他未贴出的部分代码完善而已。还请体谅作为一位新手的不易。
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值