转载请注明出处:王亟亟的大牛之路
愿意花时间写东西不容易,人啊,都是有血有肉有思想的,借鉴是学习,纯Copy就不好了,谢谢
部分资料参考于网上。
《赠梁任父同年》黄遵宪
寸寸河山寸寸金,侉离分裂力谁任?
杜鹃再拜忧天泪,精卫无穷填海心。
上一篇我们讲到了简易的封装 对我们提高效率的好处,这一篇继续写下去,如果第一篇没看过的希望能看下,方便理解。链接:亟亟在安卓的进阶实例
这一次我们利用最基本的Activity生命周期中的方法,来对用户蓝牙进行识别操作,并在过程中考虑用户层面的操作理解,顺便补充下安卓手机的蓝牙知识。
什么是蓝牙?
一种无线技术标准,可实现固定设备、移动设备和楼宇个人域网之间的短距离数据交换(使用2.4—2.485GHz的ISM波段的UHF无线电波)。
白话:安卓对各个版本的蓝牙其实都有一定的支持,从1.5的Cupcake就支持了蓝牙耳机,但是自从安卓4.3版本之后Google对蓝牙4.0的支持,又进一步的提升,所以对4.3前后的适配又成了我们的工作(现在已经普遍以5.0为开发环境低版本的手机已经不多,工作量其实已经不大了)
OK,简单介绍完了,开始今天的代码
写一个工具类BluetoothMgr,把蓝牙一些相关的操作,放在里面
/**
* Created by Ezreal on 2015/9/14.
*/
public class BluetoothMgr {
private static BluetoothMgr oneInstance = null;
public static BluetoothAdapter mBluetoothAdapter = null;
public boolean available = false;
private static List<BluetoothDevice> devList = new ArrayList<BluetoothDevice>();
private BluetoothMgr() { }
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
private BluetoothMgr(Context context) {
int sdkInt = Build.VERSION.SDK_INT;
if (sdkInt <= Build.VERSION_CODES.JELLY_BEAN_MR1) {
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
} else {
BluetoothManager manager = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = manager.getAdapter();
}
available = (null != mBluetoothAdapter);
}
//判断BluetoothMgr是否可用
public boolean available() {
return available;
}
//获得实例
public static BluetoothMgr getInstance(Context context) {
if (null == oneInstance) {
oneInstance = new BluetoothMgr(context);
}
return oneInstance;
}
//搜索设备
public static boolean startDiscovery(){
if (null == mBluetoothAdapter) {
return false;
}
if (!mBluetoothAdapter.isEnabled()) {
mBluetoothAdapter.enable();
while (!mBluetoothAdapter.isEnabled()) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
if (mBluetoothAdapter.isDiscovering()) {
return true;
}
return mBluetoothAdapter.startDiscovery();
}
//取消搜索
public static boolean cancelDiscovery() {
if (mBluetoothAdapter == null) {
return false;
}
if (mBluetoothAdapter.isDiscovering()){
return mBluetoothAdapter.cancelDiscovery();
}
return false;
}
//添加设备
public static void addOne(BluetoothDevice device) {
if (null == device) {
return;
}
if (devList.contains(device)) {
return;
}
devList.add(device);
}
//删除设备
public static void deleteOne(String mac) {
if (null == mac || mac.length()==0) {
return;
}
for (int i = 0; i < devList.size(); ++i) {
BluetoothDevice device = devList.get(i);
if (device.getAddress().equalsIgnoreCase(mac)) {
devList.remove(i);
break;
}
}
}
//清空集合
public static void clearAllDevices() {
devList.clear();
}
public static BluetoothDevice findOne(int pos) {
if (pos < 0 || pos >= devList.size()) {
return null;
}
return devList.get(pos);
}
public static List<BluetoothDevice> getDevList() {
return devList;
}
public static boolean isDevListEmpty() {
return (null == devList || devList.isEmpty());
}
//获取状态
public static int getState(){
if(mBluetoothAdapter!=null){
LogUtils.d("BluetoothMgr","mBluetoothAdapter.getState()"+mBluetoothAdapter.getState());
return mBluetoothAdapter.getState();
}else{
return -1;
}
}
}
分析:对蓝牙的一些基本方法进行了封装,以及版本的判断,这边在例举下蓝牙相关的一些具体代码的内容
(这部分网上资料还算有,也可以找找)
在安卓要使用蓝牙,先要授权
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
不然你项目一运行就是异常。
要使用蓝牙必须声明一个BluetoothAdapter
在4.3之前 mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
获取系统默认蓝牙。
4.3之后 BluetoothManager manager = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = manager.getAdapter();
列举一些常用的方法
disable()关闭蓝牙
enable()打开蓝牙(用户将不会收到提示)
下面是另一种打开蓝牙的方式,但是会提醒用户手动去打开
Intent enabler=new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enabler,reCode);//同startActivity(enabler);
cancelDiscovery() 取消搜索设备
startDiscovery() 开始搜索设备
getAddress()获取本地蓝牙地址
getName()获取本地蓝牙名称
getRemoteDevice(Stringaddress)根据蓝牙地址获取远程蓝牙设备
getState()获取本地蓝牙适配器当前状态
isDiscovering()判断当前是否正在查找设备,是返回true
isEnabled()判断蓝牙是否打开,已打开返回true,否则,返回false
再列举下蓝牙的状态值
BluetoothAdapter STATE 状态值
int STATE_OFF 蓝牙已经关闭
int STATE_ON 蓝牙已经打开
int STATE_TURNING_OFF 蓝牙处于关闭过程中 ,关闭ing
int STATE_TURNING_ON 蓝牙处于打开过程中 ,打开ing
BluetoothAdapter SCAN_MOD状态值=扫描状态
可以扫描其他设备的,当然它同时能被其他蓝牙设备扫码。
int SCAN_MODE_CONNECTABLE 表明该蓝牙可以扫描其他蓝牙设备
int SCAN_MODE_CONNECTABLE_DISCOVERABLE 可以扫描其他蓝牙设备,并且可以被其他蓝牙设备扫描到。
int SCAN_MODE_NONE : 该蓝牙不能扫描以及被扫描。
更多资料可参考BluetoothAdapter[蓝牙]
铺垫做的差不多了,我们开始今天的代码。
需求:我有一个Activity,我需要进入他的时候让用户开启手机蓝牙,然后对我们的另外一个蓝牙硬件进行操作,如果用户不愿意去开,那就停留在原有界面,如果用户去开蓝牙了并且成功了那么就进入下一步操作,如果没开成功,那么继续提示。
包结构:
代码的基类都是在我们之前的Demo中继续添加的,更有延续性。
直接贴 MainActivity
public class MainActivity extends BaseActivity implements View.OnClickListener{
Button button;
private MyPromptDlg btNotOpenDlg = null;
BluetoothMgr bleMgr;
@Override
protected void findById() {
button=(Button)findViewById(R.id.button);
bleMgr=BluetoothMgr.getInstance(this);
}
@Override
protected void setListener() {
button.setOnClickListener(this);
}
@Override
protected void logic() {
}
@Override
protected int getLayout() {
return R.layout.activity_main;
}
@Override
public void onClick(View v) {
if (v.getId()==R.id.button){
Toast.makeText(MainActivity.this,"NFC是否可用?? "+NFCisAvailable(),Toast.LENGTH_SHORT).show();
openBlueToothSetting();
}
}
@Override
protected void onResume() {
super.onResume();
LogUtils.d("------>onResume");
if(bleMgr.isEnabled()){
Toast.makeText(MainActivity.this,"蓝牙已经打开",Toast.LENGTH_SHORT).show();
}else{
OpenBlueTooth();
}
}
//打开蓝牙
private void OpenBlueTooth(){
//判断Activity的状态
if (this.isFinishing()) {
return;
}
if (null == btNotOpenDlg) {
MyPromptDlg.Builder builder = new MyPromptDlg.Builder(this);
builder.setTitle(res.getString(R.string.prompt_dlg_title))
.setText(res.getString(R.string.bt_check_message))
.setPositiveButton(res.getString(R.string.common_ok),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
int which) {
dialog.dismiss();
openBlueToothSetting();
}
})
.setNegativeButton(res.getString(R.string.common_cancel),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
int which) {
dialog.dismiss();
//finish();
}
});
btNotOpenDlg = builder.create();
btNotOpenDlg.setCancelable(false);
btNotOpenDlg.setCanceledOnTouchOutside(false);
}
if (!btNotOpenDlg.isShowing()) {
btNotOpenDlg.show();
}
}
//打开系统蓝牙设置菜单
private void openBlueToothSetting(){
Intent intent = new Intent(Settings.ACTION_BLUETOOTH_SETTINGS);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
}
分析:
首先我们在我们的onCreate方法中初始化一个BluetoothMgr并且让其获得了系统蓝牙的实例(包中的BluetoothMgr是一个Demo版的,具体更多的通用方法封装在JAR包中了)
用户进入App 依次调用onCreate–onStart–onResume–Activity进入运行状态。
我们在onCreate时并没有对用户的蓝牙状态进行判断,而是在onResume方法中判断,这是为什么?看下图
因为onResume会多次调用,而onCreate在不被回收过或者onStop的情况下永远就调用一次,我们需要每一次用户焦点在我们App中的时候都去判断蓝牙的状态,那就是为什么我们要这么做的原因。
为了提高我们App的友好度,在判断用户没有开启蓝牙的时候,我们弹出一个Dialog提示用户要不要去开蓝牙,如图
如果用户点击取消我们会回到界面,但是不会调用onResume方法,不然我们的用户 就一直在那里选啊选了,不符合逻辑。
点击是,调用openBlueToothSetting()方法去手动开启,当然如果你觉得你需要强势一些可以用enable()方法,直接就开启了,但是要记得做短暂的等待,因为开启蓝牙会有一定的异步操作。
因为你代码调用开启蓝牙所以用户回到界面之后不会再判断时候开启蓝牙,也符合我们的业务需求。
当用户点击确定的时候我们开启了蓝牙设置菜单界面(系统的)
回来之后又调用了onResume,弹出了我们的吐司
OK我们的业务就完成了,还有别的实现方法么?有!!
可以用Service,开一个现成一直在那里判断也能达到效果 但是不是最理想的实现方式
还有是BroadcastReceiver 去监听手机蓝牙的变化,实现如下
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));
记得注销哦!!
午休午休!!源码地址:http://yunpan.cn/cmCaaRkzc2UV6 访问密码 4894