Android提高之Android手机与BLE终端通信

来源:互联网 发布:python中定义矩阵 编辑:程序博客网 时间:2024/06/03 11:17

最近穿戴设备发展得很火,把相关技术也带旺了,其中一项是BLE(Bluetooth Low Energy)。BLE是蓝牙4.0的核心Profile,主打功能是快速搜索,快速连接,超低功耗保持连接和传输数据,弱点是数据传输速率低,由于BLE的低功耗特点,因此普遍用于穿戴设备。Android 4.3才开始支持BLE API,所以请各位客官把本文代码运行在蓝牙4.0和Android 4.3及其以上的系统,另外本文所用的BLE终端是一个蓝牙4.0的串口蓝牙模块。

注:笔者的i9100刷了4.4系统后,竟然也能跟BLE蓝牙模块通信。

BLE分为三部分Service、Characteristic、Descriptor,这三部分都由UUID作为唯一标示符。一个蓝牙4.0的终端可以包含多个Service,一个Service可以包含多个Characteristic,一个Characteristic包含一个Value和多个Descriptor,一个Descriptor包含一个Value。一般来说,Characteristic是手机与BLE终端交换数据的关键,Characteristic有较多的跟权限相关的字段,例如PERMISSION和PROPERTY,而其中最常用的是PROPERTY,本文所用的BLE蓝牙模块竟然没有标准的Characteristic的PERMISSION。Characteristic的PROPERTY可以通过位运算符组合来设置读写属性,例如READ|WRITE、READ|WRITE_NO_RESPONSE|NOTIFY,因此读取PROPERTY后要分解成所用的组合(本文代码已含此分解方法)。

本文代码改自Android 4.3 Sample的BluetoothLeGatt,把冗余代码去掉,获取的BLE设备信息都通过Log,还有一些必要的读写蓝牙方法,应该算是简化到大家一看就可以懂了。本文完整代码可以点击此处本站下载。

接下来贴出本文运行的结果,首先是连接BLE设备后,枚举出设备所有Service、Characteristic、Descriptor,并且手机会往Characteristic uuid=0000ffe1-0000-1000-8000-00805f9b34fb写入“send data->”字符串,BLE终端收到数据通过串口传到PC串口助手
04-21 18:28:25.465: E/DeviceScanActivity(12254): -->service type:PRIMARY
04-21 18:28:25.465: E/DeviceScanActivity(12254): -->includedServices size:0
04-21 18:28:25.465: E/DeviceScanActivity(12254): -->service uuid:00001800-0000-1000-8000-00805f9b34fb
04-21 18:28:25.465: E/DeviceScanActivity(12254): ---->char uuid:00002a00-0000-1000-8000-00805f9b34fb
04-21 18:28:25.465: E/DeviceScanActivity(12254): ---->char permission:UNKNOW
04-21 18:28:25.465: E/DeviceScanActivity(12254): ---->char property:READ
04-21 18:28:25.465: E/DeviceScanActivity(12254): ---->char uuid:00002a01-0000-1000-8000-00805f9b34fb
04-21 18:28:25.470: E/DeviceScanActivity(12254): ---->char permission:UNKNOW
04-21 18:28:25.470: E/DeviceScanActivity(12254): ---->char property:READ
04-21 18:28:25.470: E/DeviceScanActivity(12254): ---->char uuid:00002a02-0000-1000-8000-00805f9b34fb
04-21 18:28:25.470: E/DeviceScanActivity(12254): ---->char permission:UNKNOW
04-21 18:28:25.470: E/DeviceScanActivity(12254): ---->char property:READ|WRITE|
04-21 18:28:25.470: E/DeviceScanActivity(12254): ---->char uuid:00002a03-0000-1000-8000-00805f9b34fb
04-21 18:28:25.470: E/DeviceScanActivity(12254): ---->char permission:UNKNOW
04-21 18:28:25.475: E/DeviceScanActivity(12254): ---->char property:READ|WRITE|
04-21 18:28:25.475: E/DeviceScanActivity(12254): ---->char uuid:00002a04-0000-1000-8000-00805f9b34fb
04-21 18:28:25.475: E/DeviceScanActivity(12254): ---->char permission:UNKNOW
04-21 18:28:25.475: E/DeviceScanActivity(12254): ---->char property:READ
04-21 18:28:25.475: E/DeviceScanActivity(12254): -->service type:PRIMARY
04-21 18:28:25.475: E/DeviceScanActivity(12254): -->includedServices size:0
04-21 18:28:25.475: E/DeviceScanActivity(12254): -->service uuid:00001801-0000-1000-8000-00805f9b34fb
04-21 18:28:25.480: E/DeviceScanActivity(12254): ---->char uuid:00002a05-0000-1000-8000-00805f9b34fb
04-21 18:28:25.480: E/DeviceScanActivity(12254): ---->char permission:UNKNOW
04-21 18:28:25.480: E/DeviceScanActivity(12254): ---->char property:INDICATE
04-21 18:28:25.480: E/DeviceScanActivity(12254): -------->desc uuid:00002902-0000-1000-8000-00805f9b34fb
04-21 18:28:25.480: E/DeviceScanActivity(12254): -------->desc permission:UNKNOW
04-21 18:28:25.480: E/DeviceScanActivity(12254): -->service type:PRIMARY
04-21 18:28:25.480: E/DeviceScanActivity(12254): -->includedServices size:0
04-21 18:28:25.480: E/DeviceScanActivity(12254): -->service uuid:0000ffe0-0000-1000-8000-00805f9b34fb
04-21 18:28:25.480: E/DeviceScanActivity(12254): ---->char uuid:0000ffe1-0000-1000-8000-00805f9b34fb
04-21 18:28:25.480: E/DeviceScanActivity(12254): ---->char permission:UNKNOW
04-21 18:28:25.480: E/DeviceScanActivity(12254): ---->char property:READ|WRITE_NO_RESPONSE|NOTIFY|
04-21 18:28:25.490: E/DeviceScanActivity(12254): -------->desc uuid:00002902-0000-1000-8000-00805f9b34fb
04-21 18:28:25.490: E/DeviceScanActivity(12254): -------->desc permission:UNKNOW
04-21 18:28:25.490: E/DeviceScanActivity(12254): -------->desc uuid:00002901-0000-1000-8000-00805f9b34fb
04-21 18:28:25.490: E/DeviceScanActivity(12254): -------->desc permission:UNKNOW
04-21 18:28:26.025: E/DeviceScanActivity(12254): onCharRead BLE DEVICE read 0000ffe1-0000-1000-8000-00805f9b34fb -> 00
这里红字是由BluetoothGattCallback的onCharacteristicRead()回调而打出Log


史上最难PHPer笔试题
【点击进入】
40分就能月薪过万! 2000多人测试,85%准确率

以下Log是PC上的串口工具通过BLE模块发送过来,由BluetoothGattCallback的 onCharacteristicChanged()打出Log
04-21 18:30:18.260: E/DeviceScanActivity(12254): onCharWrite BLE DEVICE write 0000ffe1-0000-1000-8000-00805f9b34fb -> send data to phone
04-21 18:30:18.745: E/DeviceScanActivity(12254): onCharWrite BLE DEVICE write 0000ffe1-0000-1000-8000-00805f9b34fb -> send data to phone
04-21 18:30:19.085: E/DeviceScanActivity(12254): onCharWrite BLE DEVICE write 0000ffe1-0000-1000-8000-00805f9b34fb -> send data to phone
04-21 18:30:19.350: E/DeviceScanActivity(12254): onCharWrite BLE DEVICE write 0000ffe1-0000-1000-8000-00805f9b34fb -> send data to phone
04-21 18:30:19.605: E/DeviceScanActivity(12254): onCharWrite BLE DEVICE write 0000ffe1-0000-1000-8000-00805f9b34fb -> send data to phone
04-21 18:30:19.835: E/DeviceScanActivity(12254): onCharWrite BLE DEVICE write 0000ffe1-0000-1000-8000-00805f9b34fb -> send data to phone
04-21 18:30:20.055: E/DeviceScanActivity(12254): onCharWrite BLE DEVICE write 0000ffe1-0000-1000-8000-00805f9b34fb -> send data to phone
04-21 18:30:20.320: E/DeviceScanActivity(12254): onCharWrite BLE DEVICE write 0000ffe1-0000-1000-8000-00805f9b34fb -> send data to phone
04-21 18:30:20.510: E/DeviceScanActivity(12254): onCharWrite BLE DEVICE write 0000ffe1-0000-1000-8000-00805f9b34fb -> send data to phone
04-21 18:30:20.735: E/DeviceScanActivity(12254): onCharWrite BLE DEVICE write 0000ffe1-0000-1000-8000-00805f9b34fb -> send data to phone
04-21 18:30:21.000: E/DeviceScanActivity(12254): onCharWrite BLE DEVICE write 0000ffe1-0000-1000-8000-00805f9b34fb -> send data to phone

接下来贴出本文核心代码:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
publicclassDeviceScanActivity extendsListActivity {
 privatefinalstatic String TAG = DeviceScanActivity.class.getSimpleName();
 privatefinalstatic String UUID_KEY_DATA = "0000ffe1-0000-1000-8000-00805f9b34fb";
 
  privateLeDeviceListAdapter mLeDeviceListAdapter;
  /**搜索BLE终端*/
  privateBluetoothAdapter mBluetoothAdapter;
  /**读写BLE终端*/
  privateBluetoothLeClass mBLE;
  privatebooleanmScanning;
  privateHandler mHandler;
 
  // Stops scanning after 10 seconds.
  privatestaticfinal long SCAN_PERIOD = 10000;
 
  @Override
  publicvoidonCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    getActionBar().setTitle(R.string.title_devices);
    mHandler = newHandler();
    // Use this check to determine whether BLE is supported on the device. Then you can
    // selectively disable BLE-related features.
    if(!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
      Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show();
      finish();
    }
    // Initializes a Bluetooth adapter. For API level 18 and above, get a reference to
    // BluetoothAdapter through BluetoothManager.
    finalBluetoothManager bluetoothManager =
        (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
    mBluetoothAdapter = bluetoothManager.getAdapter();
    // Checks if Bluetooth is supported on the device.
    if(mBluetoothAdapter == null) {
      Toast.makeText(this, R.string.error_bluetooth_not_supported, Toast.LENGTH_SHORT).show();
      finish();
      return;
    }
    //开启蓝牙
    mBluetoothAdapter.enable();
    mBLE = newBluetoothLeClass(this);
    if(!mBLE.initialize()) {
      Log.e(TAG,"Unable to initialize Bluetooth");
      finish();
    }
    //发现BLE终端的Service时回调
    mBLE.setOnServiceDiscoverListener(mOnServiceDiscover);
    //收到BLE终端数据交互的事件
    mBLE.setOnDataAvailableListener(mOnDataAvailable);
  }
  @Override
  protectedvoidonResume() {
    super.onResume();
 
    // Initializes list view adapter.
    mLeDeviceListAdapter = newLeDeviceListAdapter(this);
    setListAdapter(mLeDeviceListAdapter);
    scanLeDevice(true);
  }
  @Override
  protectedvoidonPause() {
    super.onPause();
    scanLeDevice(false);
    mLeDeviceListAdapter.clear();
    mBLE.disconnect();
  }
  @Override
  protectedvoidonStop() {
    super.onStop();
    mBLE.close();
  }
  @Override
  protectedvoidonListItemClick(ListView l, View v, intposition,longid) {
    finalBluetoothDevice device = mLeDeviceListAdapter.getDevice(position);
    if(device == null)return;
    if(mScanning) {
      mBluetoothAdapter.stopLeScan(mLeScanCallback);
      mScanning = false;
    }
    mBLE.connect(device.getAddress());
  }
  privatevoidscanLeDevice(finalbooleanenable) {
    if(enable) {
      // Stops scanning after a pre-defined scan period.
      mHandler.postDelayed(newRunnable() {
        @Override
        publicvoidrun() {
          mScanning = false;
          mBluetoothAdapter.stopLeScan(mLeScanCallback);
          invalidateOptionsMenu();
        }
      }, SCAN_PERIOD);
      mScanning = true;
      mBluetoothAdapter.startLeScan(mLeScanCallback);
    }else{
      mScanning = false;
      mBluetoothAdapter.stopLeScan(mLeScanCallback);
    }
    invalidateOptionsMenu();
  }
  /**
   * 搜索到BLE终端服务的事件
   */
  privateBluetoothLeClass.OnServiceDiscoverListener mOnServiceDiscover = newOnServiceDiscoverListener(){
 
 @Override
 publicvoidonServiceDiscover(BluetoothGatt gatt) {
  displayGattServices(mBLE.getSupportedGattServices());
 }
  };
  /**
   * 收到BLE终端数据交互的事件
   */
  privateBluetoothLeClass.OnDataAvailableListener mOnDataAvailable = newOnDataAvailableListener(){
   /**
   * BLE终端数据被读的事件
   */
 @Override
 publicvoidonCharacteristicRead(BluetoothGatt gatt,
  BluetoothGattCharacteristic characteristic, intstatus) {
  if(status == BluetoothGatt.GATT_SUCCESS)
  Log.e(TAG,"onCharRead "+gatt.getDevice().getName()
   +" read "
   +characteristic.getUuid().toString()
   +" -> "
   +Utils.bytesToHexString(characteristic.getValue()));
 }
   /**
   * 收到BLE终端写入数据回调
   */
 @Override
 publicvoidonCharacteristicWrite(BluetoothGatt gatt,
  BluetoothGattCharacteristic characteristic) {
  Log.e(TAG,"onCharWrite "+gatt.getDevice().getName()
   +" write "
   +characteristic.getUuid().toString()
   +" -> "
   +newString(characteristic.getValue()));
 }
  };
  // Device scan callback.
  privateBluetoothAdapter.LeScanCallback mLeScanCallback =
      newBluetoothAdapter.LeScanCallback() {
    @Override
    publicvoidonLeScan(finalBluetoothDevice device, intrssi,byte[] scanRecord) {
      runOnUiThread(newRunnable() {
        @Override
        publicvoidrun() {
          mLeDeviceListAdapter.addDevice(device);
          mLeDeviceListAdapter.notifyDataSetChanged();
        }
      });
    }
  };
  privatevoiddisplayGattServices(List<BluetoothGattService> gattServices) {
    if(gattServices == null)return;
    for(BluetoothGattService gattService : gattServices) {
     //-----Service的字段信息-----//
     inttype = gattService.getType();
      Log.e(TAG,"-->service type:"+Utils.getServiceType(type));
      Log.e(TAG,"-->includedServices size:"+gattService.getIncludedServices().size());
      Log.e(TAG,"-->service uuid:"+gattService.getUuid());
       
      //-----Characteristics的字段信息-----//
      List<BluetoothGattCharacteristic> gattCharacteristics =gattService.getCharacteristics();
      for(finalBluetoothGattCharacteristic gattCharacteristic: gattCharacteristics) {
        Log.e(TAG,"---->char uuid:"+gattCharacteristic.getUuid());
        intpermission = gattCharacteristic.getPermissions();
        Log.e(TAG,"---->char permission:"+Utils.getCharPermission(permission));
        intproperty = gattCharacteristic.getProperties();
        Log.e(TAG,"---->char property:"+Utils.getCharPropertie(property));
        byte[] data = gattCharacteristic.getValue();
     if(data != null&& data.length > 0) {
      Log.e(TAG,"---->char value:"+newString(data));
     }
     //UUID_KEY_DATA是可以跟蓝牙模块串口通信的Characteristic
     if(gattCharacteristic.getUuid().toString().equals(UUID_KEY_DATA)){     
      //测试读取当前Characteristic数据,会触发mOnDataAvailable.onCharacteristicRead()
      mHandler.postDelayed(newRunnable() {
            @Override
            publicvoidrun() {
             mBLE.readCharacteristic(gattCharacteristic);
            }
          },500);
      //接受Characteristic被写的通知,收到蓝牙模块的数据后会触发mOnDataAvailable.onCharacteristicWrite()
      mBLE.setCharacteristicNotification(gattCharacteristic,true);
      //设置数据内容
      gattCharacteristic.setValue("send data->");
      //往蓝牙模块写入数据
      mBLE.writeCharacteristic(gattCharacteristic);
     }
     //-----Descriptors的字段信息-----//
  List<BluetoothGattDescriptor> gattDescriptors = gattCharacteristic.getDescriptors();
  for(BluetoothGattDescriptor gattDescriptor : gattDescriptors) {
   Log.e(TAG,"-------->desc uuid:" + gattDescriptor.getUuid());
   intdescPermission = gattDescriptor.getPermissions();
   Log.e(TAG,"-------->desc permission:"+ Utils.getDescPermission(descPermission));
   byte[] desData = gattDescriptor.getValue();
   if(desData != null&& desData.length > 0) {
   Log.e(TAG,"-------->desc value:"+newString(desData));
   }
      }
      }
    }//
  }
}

感兴趣的读者可以动手测试一下代码的运行情况,希望能对大家的Android项目开发有所帮助。


分享一个集成目前主流蓝牙的demo、android蓝牙4.0开发、项目中使用到了搜索BLE终端和读写BLE终端、另外还有在程序里面开房蓝牙、在Demo里面还处理了收到BLE终端数据交互的事件、代码里都有中文注释、要读性应该非常好的、应该会对开发有一定帮助、有兴趣的哥们可以下载看看

android蓝牙4.0开发


onCreate代码

@Overridepublic void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    getActionBar().setTitle(R.string.title_devices);    mHandler = new Handler();    // Use this check to determine whether BLE is supported on the device.  Then you can    // selectively disable BLE-related features.    if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {        Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show();        finish();    }    // Initializes a Bluetooth adapter.  For API level 18 and above, get a reference to    // BluetoothAdapter through BluetoothManager.    final BluetoothManager bluetoothManager =            (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);    mBluetoothAdapter = bluetoothManager.getAdapter();        // Checks if Bluetooth is supported on the device.    if (mBluetoothAdapter == null) {        Toast.makeText(this, R.string.error_bluetooth_not_supported, Toast.LENGTH_SHORT).show();        finish();        return;    }    //开启蓝牙    mBluetoothAdapter.enable();        mBLE = new BluetoothLeClass(this);    if (!mBLE.initialize()) {        Log.e(TAG, "Unable to initialize Bluetooth");        finish();    }    //发现BLE终端的Service时回调    mBLE.setOnServiceDiscoverListener(mOnServiceDiscover);    //收到BLE终端数据交互的事件    mBLE.setOnDataAvailableListener(mOnDataAvailable);}


<iframe id="iframeu2248002_0" src="http://pos.baidu.com/uchm?rdid=2248002&amp;dc=2&amp;exps=112016&amp;di=u2248002&amp;dri=0&amp;dis=0&amp;dai=2&amp;ps=1510x184&amp;dcb=BAIDU_SSP_define&amp;dtm=BAIDU_DUP_SETJSONADSLOT&amp;dvi=0.0&amp;dci=-1&amp;dpt=none&amp;tsr=0&amp;tpr=1468477465848&amp;ti=Android%E8%93%9D%E7%89%994.0%E5%BC%80%E5%8F%91_%E8%93%9D%E7%89%99%E5%BC%80%E5%8F%91%E5%AE%9E%E4%BE%8B%E6%BA%90%E7%A0%81%E4%B8%8B%E8%BD%BD_DD%E5%8D%9A%E5%AE%A2&amp;ari=1&amp;dbv=2&amp;drs=1&amp;pcs=1349x632&amp;pss=1349x1543&amp;cfv=0&amp;cpl=23&amp;chi=1&amp;cce=true&amp;cec=UTF-8&amp;tlm=1468477465&amp;rw=632&amp;ltu=http%3A%2F%2Fdwtedx.com%2Fitshare_447.html&amp;ltr=https%3A%2F%2Fwww.baidu.com%2Flink%3Furl%3DgbHWAKf8724p-Jh30maMxa-l_bPUOtE9ftaiwVZCe2RNf_-zKpOSxGIZ80I10MBy%26wd%3D%26eqid%3D809ab9b10002334b0000000257872a5d&amp;ecd=1&amp;psr=1366x768&amp;par=1366x728&amp;pis=-1x-1&amp;ccd=24&amp;cja=false&amp;cmi=34&amp;col=zh-CN&amp;cdo=-1&amp;tcn=1468477466&amp;qn=c1f1335952e3b2e0&amp;tt=1468477465819.159.547.548" width="120" height="45" align="center,center" vspace="0" hspace="0" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" allowtransparency="true" style="margin: 0px; padding: 0px; border-width: 0px; border-style: initial; outline: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit;font-size:undefined; line-height: inherit; font-family: inherit; word-wrap: break-word; vertical-align: bottom;"></iframe>

收到BLE终端数据交互的事件

/** * 收到BLE终端数据交互的事件 */private BluetoothLeClass.OnDataAvailableListener mOnDataAvailable = new OnDataAvailableListener(){    /**     * BLE终端数据被读的事件     */    @Override    public void onCharacteristicRead(BluetoothGatt gatt,            BluetoothGattCharacteristic characteristic, int status) {        if (status == BluetoothGatt.GATT_SUCCESS)             Log.e(TAG,"onCharRead " gatt.getDevice().getName()                     " read "                     characteristic.getUuid().toString()                     " -> "                     Utils.bytesToHexString(characteristic.getValue()));    }        /**     * 收到BLE终端写入数据回调     */    @Override    public void onCharacteristicWrite(BluetoothGatt gatt,            BluetoothGattCharacteristic characteristic) {        Log.e(TAG,"onCharWrite " gatt.getDevice().getName()                 " write "                 characteristic.getUuid().toString()                 " -> "                 new String(characteristic.getValue()));    }};


最后给贴上Demo的源代码、希望对大家有用、有兴趣的哥们可以下载看看


0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 小区总有小年青骑摩托车扰民怎么办 摩托车行驶证副本丢了怎么办 摩托车驾照副本丢了怎么办 公司行驶证掉了怎么办 身份证外迁了过户的话怎么办 驾照体检报告丢了怎么办 常州医保卡丢了怎么办 驾驶证违章罚单丢了怎么办 身份证被别人办了信用卡怎么办 被别人办了信用卡怎么办 考驾照体检忘带身份证怎么办 c证扣12分怎么办新规 c照12分不够扣怎么办 扣了18分怎么办一次性 c照累计扣12分怎么办 车辆超速扣12分怎么办 一次超速扣12分怎么办 分扣了罚款未交怎么办 c照一次扣12分怎么办 人在外地身份证到期了怎么办 手机进水了屏幕不亮怎么办 北京一证通过期怎么办 小米6音量键进水怎么办 考驾照怕过不了怎么办 学车对车没感觉怎么办 居住证到期2个月怎么办 生育险差一个月怎么办 驾照扣了38分怎么办 新疆转入山东上学怎么办手续 驾照过日期换证怎么办 机动车被扣24分怎么办 车辆被扣24分怎么办 现在深圳牌十年老车怎么办? 护士证过期4年了怎么办 护士资格证延续注册过期了怎么办 护士资格证过期没注册怎么办 护士资格证注册时间过期怎么办 辅警体检视力不行怎么办 护士延续注册体检怀孕怎么办 护士资格证没有延续注册怎么办 申请信用卡没有座机号码怎么办