要须心地收汗马,孔孟行世目杲杲。这篇文章主要讲述Android|安卓精准计步器并通过蓝牙实现对战PK功能相关的知识,希望能为你提供帮助。
android计步器软件,并添加定位功能和步数PK功能。计步器功能实现
本章节功能实现参考:http://blog.csdn.net/linglongxin24/article/details/52868803记步算法参考
- 算法一
- 算法二
添加权限
1< !--计歩需要的权限--> 2< uses-permission android:name="android.permission.VIBRATE" /> 3< uses-permission android:name="android.permission.WRITE_SETTINGS" /> 4< uses-feature android:name="android.hardware.sensor.accelerometer" /> 5< uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> 6< uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" /> 7< uses-feature 8android:name="android.hardware.sensor.stepcounter" 9android:required="true" /> 10< uses-feature 11android:name="android.hardware.sensor.stepdetector" 12android:required="true" />
检测手机是否支持记步
/** * 判断该设备是否支持计歩 * * @param context * @return */ @TargetApi(Build.VERSION_CODES.KITKAT) public static boolean isSupportStepCountSensor(Context context) { // 获取传感器管理器的实例 SensorManager sensorManager = (SensorManager) context .getSystemService(context.SENSOR_SERVICE); Sensor countSensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER); Sensor detectorSensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_DETECTOR); return countSensor != null || detectorSensor != null; }
功能使用
1private boolean isBind = false; 2private Messenger mGetReplyMessenger = new Messenger(new Handler(this)); 3private Messenger messenger; 4 5/** 6* 开启计步服务 7*/ 8private void setupService() { 9Intent intent = new Intent(this, StepService.class); 10isBind = bindService(intent, conn, Context.BIND_AUTO_CREATE); 11startService(intent); 12 13 14} 15/** 16* 从service服务中拿到步数 17* 18* @param msg 19* @return 20*/ 21@Override 22public boolean handleMessage(Message msg) { 23switch (msg.what) { 24case Constant.MSG_FROM_SERVER: 25cc.setCurrentCount(10000, msg.getData().getInt("step")); 26break; 27} 28return false; 29} 30 31 32/** 33* 用于查询应用服务(application Service)的状态的一种interface, 34* 更详细的信息可以参考Service 和 context.bindService()中的描述, 35* 和许多来自系统的回调方式一样,ServiceConnection的方法都是进程的主线程中调用的。 36*/ 37ServiceConnection conn = new ServiceConnection() { 38/** 39* 在建立起于Service的连接时会调用该方法,目前Android是通过IBind机制实现与服务的连接。 40* @param name 实际所连接到的Service组件名称 41* @param service 服务的通信信道的IBind,可以通过Service访问对应服务 42*/ 43@Override 44public void onServiceConnected(ComponentName name, IBinder service) { 45try { 46messenger = new Messenger(service); 47Message msg = Message.obtain(null, Constant.MSG_FROM_CLIENT); 48msg.replyTo = mGetReplyMessenger; 49messenger.send(msg); 50} catch (RemoteException e) { 51e.printStackTrace(); 52} 53} 54 55/** 56* 当与Service之间的连接丢失的时候会调用该方法, 57* 这种情况经常发生在Service所在的进程崩溃或者被Kill的时候调用, 58* 此方法不会移除与Service的连接,当服务重新启动的时候仍然会调用 onServiceConnected()。 59* @param name 丢失连接的组件名称 60*/ 61@Override 62public void onServiceDisconnected(ComponentName name) { 63 64} 65};
效果展示
文章图片
文章图片
【Android|安卓精准计步器并通过蓝牙实现对战PK功能】
GPS定位的实现 添加权限
< !-- 连接互联网Internet权限 --> < uses-permission android:name="android.permission.INTERNET" /> < !-- GPS定位权限 --> < uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> < uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> < !-- 这个权限用于进行网络定位 --> < permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> < !-- 这个权限用于访问GPS定位 --> < permission android:name="android.permission.ACCESS_FINE_LOCATION" />
实现定位服务
private void getLocation() { info_latitude = (TextView) findViewById(R.id.gps_latitude); info_longitude = (TextView) findViewById(R.id.gps_longitude); locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) { // 如果gps打开 getLocationInfo(); } else { // 如果没有打开gps toggleGPS(); new Handler() { }.postDelayed(new Runnable() { @Override public void run() { getLocationInfo(); } }, 2000); } }
调用系统设置打开GPS
private void toggleGPS() { Intent gpsIntent = new Intent(); gpsIntent.setClassName("com.android.settings", "com.android.settings.widget.SettingsAppWidgetProvider"); gpsIntent.addCategory("android.intent.category.ALTERNATIVE"); gpsIntent.setData(Uri.parse("custom:3")); try { PendingIntent.getBroadcast(this, 0, gpsIntent, 0).send(); } catch (PendingIntent.CanceledException e) { e.printStackTrace(); try { locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 1000, 0, locationListener); Location location1 = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER); if(location1 != null) { latitude = location1.getLatitude(); longitude = location1.getLongitude(); } } catch (SecurityException e1) { e1.printStackTrace(); info_latitude.setText("纬度获取异常"); info_longitude.setText("经度获取异常"); }} }
监听位置变化并显示经纬度信息
private void getLocationInfo() { try { Location location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER); if (location != null) { latitude = location.getLatitude(); longitude = location.getLongitude(); } else { locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 0, locationListener); } if (latitude == 0.0 & & longitude == 0.0) { info_longitude.setText("经纬度获取异常,请退出后重进,"); info_latitude.setText("并且确保位置服务开启!"); } else { info_latitude.setText("纬度:" + latitude); info_longitude.setText("经度:" + longitude); } } catch (SecurityException e) { e.printStackTrace(); info_latitude.setText("纬度获取异常"); info_longitude.setText("经度获取异常"); } } // 监听位置变化 LocationListener locationListener = new LocationListener() { // 当坐标改变时触发此函数,如果Provider传进相同的坐标,它就不会被触发 @Override public void onLocationChanged(Location location) { if (location != null) { latitude = location.getLatitude(); // 经度 longitude = location.getLongitude(); // 纬度 } } // provider的状态在可用、暂时不可用和无服务三个状态下直接切换时触发这个函数 @Override public void onStatusChanged(String s, int i, Bundle bundle) { } // provider被enable时触发这个函数,比如GPS被打开 @Override public void onProviderEnabled(String s) { } // Provider被disable时触发此函数,比如GPS被关闭 @Override public void onProviderDisabled(String s) { } };
蓝牙对战PK功能实现 添加权限
< uses-permission android:name="android.permission.BLUETOOTH"/> < uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/> < uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />
初始化蓝牙服务
// 在APP启动时检查蓝牙状态 @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2) private void initBle() { bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); bluetoothAdapter = bluetoothManager.getAdapter(); if (bluetoothAdapter == null) { Toast.makeText(this, "本设备不支持蓝牙!", Toast.LENGTH_LONG).show(); return; }// 如果没有打开蓝牙 if (!bluetoothAdapter.isEnabled()) { Toast.makeText(this,"本APP需要蓝牙服务,请打开蓝牙!",Toast.LENGTH_LONG).show(); Intent enableBleIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult(enableBleIntent,REQUEST_ENABLE_BT); } // 如果蓝牙打开,进行广播注册 if (bluetoothAdapter.isEnabled()) { // 蓝牙广播注册 registerBluetooth(); } }
蓝牙广播注册
private IntentFilter intentFilter; void registerBluetooth() { intentFilter = makeFilter(); registerReceiver(bluetoothReceiver,intentFilter); }// 注册蓝牙广播,当扫描到设备时方便做处理 /** * 蓝牙广播过滤器 * 蓝牙状态改变 * 找到设备 * 扫描完成 * 开始扫描 * 状态改变 * */public IntentFilter makeFilter() { IntentFilter filter = new IntentFilter(); filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); //蓝牙状态改变的广播 filter.addAction(BluetoothDevice.ACTION_FOUND); //找到设备的广播 filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); //搜索完成的广播 filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED); //开始扫描的广播 filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED); //状态改变 filter.addAction(BluetoothDevice.ACTION_FOUND); //搜索蓝压设备,每搜到一个设备发送一条广播 filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED); //配对开始时,配对成功时 filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED); //配对时,发起连接 filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED); filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED); //配对结束时,断开连接 filter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED); filter.addAction(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED); //更改蓝牙名称,打开蓝牙时,可能会调用多次 filter.addAction(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE); filter.addAction(BluetoothAdapter.ACTION_REQUEST_ENABLE); filter.addAction(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED); //搜索模式改变 return filter; }
蓝牙搜索回调
// 蓝牙开始搜索的回调 private BroadcastReceiver bluetoothReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); final BluetoothDevice device; if (action.equals(BluetoothDevice.ACTION_FOUND)) { device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); String bleMessage = device.getName() + "> > " + device.getAddress(); // 已匹配的设备 if (device.getBondState() == BluetoothDevice.BOND_BONDED) { // 此处的adapter是列表的adapter if (!bluetoothList.contains(bleMessage + "> > (已配对)")) { bluetoothList.add(bleMessage + "> > (已配对)"); aAdapter.notifyDataSetChanged(); } } else { if (!bluetoothList.contains(bleMessage + "> > (未配对)")) { bluetoothList.add(bleMessage + "> > (未配对)"); aAdapter.notifyDataSetChanged(); } } } } };
蓝牙搜索
// 搜索蓝牙 private void doSearchBle() { Intent enabler = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE); startActivity(enabler); if (bluetoothList == null || !bluetoothList.isEmpty()) { assert bluetoothList != null; bluetoothList.clear(); aAdapter.notifyDataSetChanged(); }// 如果蓝牙打开,进行广播注册 if (bluetoothAdapter.isEnabled()) { // 蓝牙广播注册 registerBluetooth(); } else { Toast.makeText(MainActivity.this,"蓝牙未开启!",Toast.LENGTH_SHORT).show(); return; }/** * 开启蓝牙服务端 * */ ThreadPoolProxyFactory.getNormalThreadPoolProxy().execute(new Runnable() { @Override public void run() { BltService bltService = new BltService(bluetoothAdapter,app_context); bltService.startBluService(); } }); if (bluetoothAdapter.isDiscovering()) { // 判断蓝牙是否正在扫描,如果是,调用取消方法,如果不是,则开始扫面 bluetoothAdapter.cancelDiscovery(); } bluetoothAdapter.startDiscovery(); }
ListView点击实现
// listView点击的实现 void listViewClick() { ble_list_view.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView< ?> adapterView, View view, final int i, long l) { bluetoothAdapter.cancelDiscovery(); String info = bluetoothList.get(i); String[] tempBleInfo = info.split("> > "); String tempAddress; if (tempBleInfo.length < 3) { return; } tempAddress = tempBleInfo[1]; BluetoothDevice de = bluetoothAdapter.getRemoteDevice(tempAddress); if (de.getBondState() == BluetoothDevice.BOND_BONDED) { // 已绑定的进入连接 startConnect(de); } else { // 未绑定的先配对 try { Method createBond = BluetoothDevice.class.getMethod("createBond"); createBond.invoke(de); } catch (Exception e) { e.printStackTrace(); Toast.makeText(MainActivity.this, "无法执行配对", Toast.LENGTH_SHORT).show(); } } }}); }
蓝牙连接
// 与蓝牙设备连接的业务代码 private void startConnect(final BluetoothDevice bluetoothDevice) { // 连接之前把扫描关闭 if (bluetoothAdapter.isDiscovering()) { // 判断蓝牙是否正在扫描,如果是,调用取消方法,如果不是,则开始扫面 bluetoothAdapter.cancelDiscovery(); } ThreadPoolProxyFactory.getNormalThreadPoolProxy().execute(new Runnable() { @Override public void run() { connect(bluetoothDevice); } }); }private int connectsuccess = 12; //连接成功 private void connect(BluetoothDevice bluetoothDevice) { try { mBluetoothSocket = bluetoothDevice.createRfcommSocketToServiceRecord(BltConstant.SPP_UUID); if (mBluetoothSocket != null) { //app_bluetoothSocket = mBluetoothSocket; if (bluetoothAdapter.isDiscovering()) { bluetoothAdapter.cancelDiscovery(); } if (!mBluetoothSocket.isConnected()) { mBluetoothSocket.connect(); } EventBus.getDefault().post(new BluRxBean(connectsuccess, bluetoothDevice)); /** // 蓝牙连接成功后,开启消息接收端,移动到eventBus的主动连接或者被动连接成功之后 ThreadPoolProxyFactory.getNormalThreadPoolProxy().execute(new Runnable() { @Override public void run() { new ReceiveSocketService().receiveMessage(); } }); **/ }} catch (IOException e) { e.printStackTrace(); try { mBluetoothSocket.close(); } catch (IOException e1) { e1.printStackTrace(); } }}
开启蓝牙服务端
public void startBluService() { try { if (BltManager.getInstance().getmBluetoothAdapter() != null) { bluetoothServerSocket = BltManager.getInstance().getmBluetoothAdapter().listenUsingRfcommWithServiceRecord("hlq.bluetooth", BltConstant.SPP_UUID); } } catch (IOException e) { } try { bluetoothServerSocket = bluetoothAdapter.listenUsingRfcommWithServiceRecord(bluetoothAdapter.getDefaultAdapter().getName(), BltConstant.SPP_UUID); socket = bluetoothServerSocket.accept(); if (socket != null) { MainActivity.mBluetoothSocket = socket; EventBus.getDefault().post(new BluRxBean(11, socket.getRemoteDevice())); //如果你的蓝牙设备只是一对一的连接,则执行以下代码 bluetoothServerSocket.close(); //如果你的蓝牙设备是一对多的,则应该调用break;跳出循环 //break; } } catch (IOException e) { e.printStackTrace(); } }
开启蓝牙消息接收端
public void receiveMessage() { if (MainActivity.mBluetoothSocket == null) { return; } try { InputStream inputStream = MainActivity.mBluetoothSocket.getInputStream(); // 从客户端获取信息 BufferedReader bff = new BufferedReader(new InputStreamReader(inputStream)); String json; while (true) { while((json = bff.readLine()) != null) { EventBus.getDefault().post(new MessageBean(RECEIVER_MESSAGE, json)); } } } catch (IOException e) { e.printStackTrace(); } }
通过EventBus实现状态监听与相关功能
@Subscribe(threadMode = ThreadMode.MAIN) public void onMessageEvent(Object obj) { if (obj instanceof MessageBean) { MessageBean messageBean = (MessageBean) obj; switch (messageBean.getId()) { case 21: String msg = messageBean.getContent(); //SendSocketService.sendMessage(String.valueOf(own_step)); // 如果是pk请求,返回自己的步数 if (msg.equals(PkConstant.PK_REQUEST)) { SendSocketService.sendMessage(PkConstant.PK_RESPOND + ":" + String.valueOf(own_step)); } // 如果是pk响应,则进行步数比较 if (msg.startsWith(PkConstant.PK_RESPOND)) { String[] temp = msg.split(":"); int enemy_step; try { enemy_step = Integer.parseInt(temp[1]); stepPk(own_step,enemy_step); } catch (Exception e) { Toast.makeText(MainActivity.this,"接收到非法数据!",Toast.LENGTH_SHORT).show(); } } break; case BltConstant.SEND_TEXT_SUCCESS: //Toast.makeText(MainActivity.this,"发送了数据!",Toast.LENGTH_SHORT).show(); // 发送了消息 break; default: break; } }if (obj instanceof BluRxBean) { BluRxBean bluRxBean = (BluRxBean) obj; switch (bluRxBean.getId()) { case 2: //Toast.makeText(MainActivity.this,"蓝牙扫描完成",Toast.LENGTH_SHORT).show(); break; case 3: Toast.makeText(MainActivity.this,"开始扫描蓝牙...",Toast.LENGTH_SHORT).show(); break; case 4: //Toast.makeText(MainActivity.this,"蓝牙配对成功!",Toast.LENGTH_SHORT).show(); break; case 11: case 12: // 由于状态码11和12分别为被连接和主动连接,所以当两个连接成功之一时,启动消息接收端 ThreadPoolProxyFactory.getNormalThreadPoolProxy().execute(new Runnable() { @Override public void run() { new ReceiveSocketService().receiveMessage(); } }); Toast.makeText(MainActivity.this,"蓝牙已连接",Toast.LENGTH_SHORT).show(); break; default: break; } } }
PK效果展示
文章图片
推荐阅读
- 通用Mapper的使用
- 使用C#的DAPPER 进行增删改查操作(准备工作)
- 手动实现applycallbind
- Android Studio安装flutter插件后找不到设备(no devices)
- SpringBoot org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): mapper.x
- Android实现头像圆角
- 《实现获取appPackage和appActivity的方法》
- 7种最佳Windows VPS和云托管
- 6个很棒的WordPress托管Google Cloud托管平台