Java tutorial
/* * Copyright 2016 Junk Chen * * 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 com.junkchen.blelib.sample; import android.Manifest; import android.app.ProgressDialog; import android.bluetooth.BluetoothGatt; import android.bluetooth.BluetoothGattCharacteristic; import android.bluetooth.BluetoothGattService; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; import android.content.pm.PackageManager; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.support.annotation.NonNull; import android.support.v4.app.ActivityCompat; import android.support.v4.content.ContextCompat; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.View; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.ListView; import android.widget.TextView; import android.widget.Toast; import com.junkchen.blelib.BleService; import com.junkchen.blelib.sample.adapter.CommonAdapter; import com.junkchen.blelib.sample.adapter.ViewHolder; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class BleScanActivity extends AppCompatActivity { //Debugging private static final String TAG = BleScanActivity.class.getSimpleName(); //Constant public static final int SERVICE_BIND = 1; public static final int SERVICE_SHOW = 2; public static final int REQUEST_CODE_ACCESS_COARSE_LOCATION = 1; //Member fields private BleService mBleService; private boolean mIsBind; private CommonAdapter<Map<String, Object>> deviceAdapter; private ArrayAdapter<String> serviceAdapter; private List<Map<String, Object>> deviceList; private String connDeviceName; private String connDeviceAddress; //Layout view private Button btn_scanBle; private ListView lstv_devList; private ListView lstv_showService; private ServiceConnection serviceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { mBleService = ((BleService.LocalBinder) service).getService(); if (mBleService != null) mHandler.sendEmptyMessage(SERVICE_BIND); if (mBleService.initialize()) { if (mBleService.enableBluetooth(true)) { verifyIfRequestPermission(); Toast.makeText(BleScanActivity.this, "Bluetooth was opened", Toast.LENGTH_SHORT).show(); } } else { Toast.makeText(BleScanActivity.this, "not support Bluetooth", Toast.LENGTH_SHORT).show(); } } @Override public void onServiceDisconnected(ComponentName name) { mBleService = null; mIsBind = false; } }; private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case SERVICE_BIND: setBleServiceListener(); break; case SERVICE_SHOW: serviceAdapter.notifyDataSetChanged(); break; } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_ble_scan); initView(); initAdapter(); registerReceiver(bleReceiver, makeIntentFilter()); doBindService(); } private void verifyIfRequestPermission() { if (Build.VERSION.SDK_INT >= 23) { Log.i(TAG, "onCreate: checkSelfPermission"); if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { Log.i(TAG, "onCreate: Android 6.0 ???"); if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.READ_CONTACTS)) { Log.i(TAG, "*********onCreate: shouldShowRequestPermissionRationale**********"); Toast.makeText(this, "??????", Toast.LENGTH_SHORT) .show(); } else { ActivityCompat.requestPermissions(this, new String[] { Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION }, REQUEST_CODE_ACCESS_COARSE_LOCATION); } } else { showDialog(getResources().getString(R.string.scanning)); mBleService.scanLeDevice(true); } } else { showDialog(getResources().getString(R.string.scanning)); mBleService.scanLeDevice(true); } } @Override protected void onDestroy() { super.onDestroy(); doUnBindService(); unregisterReceiver(bleReceiver); } @Override public void onBackPressed() { if (mBleService.isScanning()) { mBleService.scanLeDevice(false); return; } super.onBackPressed(); } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { if (requestCode == REQUEST_CODE_ACCESS_COARSE_LOCATION) { Log.i(TAG, "onRequestPermissionsResult: permissions.length = " + permissions.length + ", grantResults.length = " + grantResults.length); if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // permission was granted, yay! Do the // contacts-related task you need to do. showDialog(getResources().getString(R.string.scanning)); mBleService.scanLeDevice(true); } else { // permission denied, boo! Disable the // functionality that depends on this permission. Toast.makeText(BleScanActivity.this, "?????ble", Toast.LENGTH_SHORT).show(); } } else { super.onRequestPermissionsResult(requestCode, permissions, grantResults); } } private void initView() { btn_scanBle = (Button) findViewById(R.id.btn_scanBle); lstv_devList = (ListView) findViewById(R.id.lstv_devList); lstv_showService = (ListView) findViewById(R.id.lstv_showService); TextView txtv = new TextView(this); txtv.setText("Services"); lstv_showService.addHeaderView(txtv); lstv_showService.setVisibility(View.VISIBLE); btn_scanBle.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (!mBleService.isScanning()) { verifyIfRequestPermission(); // mBleService.close(); deviceList.clear(); mBleService.scanLeDevice(true); } } }); lstv_showService.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Log.i(TAG, "position = " + position + ", id = " + id); String s = serviceList.get((int) id); Intent intent = new Intent(BleScanActivity.this, CharacteristicActivity.class); intent.putExtra("characteristic", characteristicList.get((int) id)); startActivity(intent); } }); } private void initAdapter() { deviceList = new ArrayList<>(); deviceAdapter = new CommonAdapter<Map<String, Object>>(this, R.layout.item_device, deviceList) { @Override public void convert(ViewHolder holder, final Map<String, Object> deviceMap) { holder.setText(R.id.txtv_name, deviceMap.get("name").toString()); holder.setText(R.id.txtv_address, deviceMap.get("address").toString()); holder.setText(R.id.txtv_connState, ((boolean) deviceMap.get("isConnect")) ? getResources().getString(R.string.state_connected) : getResources().getString(R.string.state_disconnected)); holder.setText(R.id.btn_connect, ((boolean) deviceMap.get("isConnect")) ? getResources().getString(R.string.disconnected) : getResources().getString(R.string.connected)); holder.getView(R.id.btn_connect).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if ((boolean) deviceMap.get("isConnect")) { mBleService.disconnect(); showDialog(getString(R.string.disconnecting)); } else { connDeviceAddress = (String) deviceMap.get("address"); connDeviceName = (String) deviceMap.get("name"); HashMap<String, Object> connDevMap = new HashMap<String, Object>(); connDevMap.put("name", connDeviceName); connDevMap.put("address", connDeviceAddress); connDevMap.put("isConnect", false); deviceList.clear(); deviceList.add(connDevMap); deviceAdapter.notifyDataSetChanged(); mBleService.connect(connDeviceAddress); showDialog(getString(R.string.connecting)); } } }); } }; lstv_devList.setAdapter(deviceAdapter); serviceList = new ArrayList<>(); serviceAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, serviceList); lstv_showService.setAdapter(serviceAdapter); } private List<BluetoothGattService> gattServiceList; private List<String> serviceList; private List<String[]> characteristicList; private void setBleServiceListener() { mBleService.setOnServicesDiscoveredListener(new BleService.OnServicesDiscoveredListener() { @Override public void onServicesDiscovered(BluetoothGatt gatt, int status) { if (status == BluetoothGatt.GATT_SUCCESS) { gattServiceList = gatt.getServices(); characteristicList = new ArrayList<>(); serviceList.clear(); for (BluetoothGattService service : gattServiceList) { String serviceUuid = service.getUuid().toString(); serviceList.add(MyGattAttributes.lookup(serviceUuid, "Unknown") + "\n" + serviceUuid); Log.i(TAG, MyGattAttributes.lookup(serviceUuid, "Unknown") + "\n" + serviceUuid); List<BluetoothGattCharacteristic> characteristics = service.getCharacteristics(); String[] charArra = new String[characteristics.size()]; for (int i = 0; i < characteristics.size(); i++) { String charUuid = characteristics.get(i).getUuid().toString(); charArra[i] = MyGattAttributes.lookup(charUuid, "Unknown") + "\n" + charUuid; } characteristicList.add(charArra); } mHandler.sendEmptyMessage(SERVICE_SHOW); } } }); // //Ble?? // mBleService.setOnLeScanListener(new BleService.OnLeScanListener() { // @Override // public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) { // //???Ble????? // } // }); // //Ble // mBleService.setOnConnectListener(new BleService.OnConnectListener() { // @Override // public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { // if (newState == BluetoothProfile.STATE_DISCONNECTED) { // //Ble // } else if (newState == BluetoothProfile.STATE_CONNECTING) { // //Ble // } else if (newState == BluetoothProfile.STATE_CONNECTED) { // //Ble // } else if (newState == BluetoothProfile.STATE_DISCONNECTING) { // //Ble // } // } // }); // //Ble?? // mBleService.setOnServicesDiscoveredListener(new BleService.OnServicesDiscoveredListener() { // @Override // public void onServicesDiscovered(BluetoothGatt gatt, int status) { // // } // }); // //Ble? // mBleService.setOnDataAvailableListener(new BleService.OnDataAvailableListener() { // @Override // public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { // //??? // } // // @Override // public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { // //?? // } // @Override // public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) { // // } // }); mBleService.setOnReadRemoteRssiListener(new BleService.OnReadRemoteRssiListener() { @Override public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) { Log.i(TAG, "onReadRemoteRssi: rssi = " + rssi); } }); } private void doOperation() { // mBleService.initialize();//Ble?? // mBleService.enableBluetooth(boolean enable);//? // mBleService.scanLeDevice(boolean enable, long scanPeriod);//????Ble // mBleService.connect(String address);//Ble // mBleService.disconnect();//? // mBleService.getSupportedGattServices();//?? // mBleService.setCharacteristicNotification(BluetoothGattCharacteristic characteristic, // boolean enabled);// // mBleService.readCharacteristic(BluetoothGattCharacteristic characteristic);//?? // mBleService.writeCharacteristic(BluetoothGattCharacteristic characteristic, byte[] value);//? // mBleService.close();// } /** * ? */ private void doBindService() { Intent serviceIntent = new Intent(this, BleService.class); bindService(serviceIntent, serviceConnection, Context.BIND_AUTO_CREATE); } /** * ? */ private void doUnBindService() { if (mIsBind) { unbindService(serviceConnection); mBleService = null; mIsBind = false; } } private BroadcastReceiver bleReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals(BleService.ACTION_BLUETOOTH_DEVICE)) { String tmpDevName = intent.getStringExtra("name"); String tmpDevAddress = intent.getStringExtra("address"); Log.i(TAG, "name: " + tmpDevName + ", address: " + tmpDevAddress); HashMap<String, Object> deviceMap = new HashMap<>(); deviceMap.put("name", tmpDevName); deviceMap.put("address", tmpDevAddress); deviceMap.put("isConnect", false); deviceList.add(deviceMap); deviceAdapter.notifyDataSetChanged(); } else if (intent.getAction().equals(BleService.ACTION_GATT_CONNECTED)) { deviceList.get(0).put("isConnect", true); deviceAdapter.notifyDataSetChanged(); dismissDialog(); } else if (intent.getAction().equals(BleService.ACTION_GATT_DISCONNECTED)) { deviceList.get(0).put("isConnect", false); serviceList.clear(); characteristicList.clear(); deviceAdapter.notifyDataSetChanged(); serviceAdapter.notifyDataSetChanged(); dismissDialog(); } else if (intent.getAction().equals(BleService.ACTION_SCAN_FINISHED)) { btn_scanBle.setEnabled(true); dismissDialog(); } } }; private static IntentFilter makeIntentFilter() { final IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(BleService.ACTION_BLUETOOTH_DEVICE); intentFilter.addAction(BleService.ACTION_GATT_CONNECTED); intentFilter.addAction(BleService.ACTION_GATT_DISCONNECTED); intentFilter.addAction(BleService.ACTION_SCAN_FINISHED); return intentFilter; } /** * Show dialog */ private ProgressDialog progressDialog; private void showDialog(String message) { progressDialog = new ProgressDialog(this); progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); progressDialog.setCanceledOnTouchOutside(false); progressDialog.setMessage(message); progressDialog.show(); } private void dismissDialog() { if (progressDialog == null) return; progressDialog.dismiss(); progressDialog = null; } }