Android|安卓精准计步器并通过蓝牙实现对战PK功能
计步器功能实现
本章节功能实现参考:http://blog.csdn.net/linglongxin24/article/details/52868803
记步算法参考
添加权限
<!--计歩需要的权限-->
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-feature android:name="android.hardware.sensor.accelerometer" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<uses-feature
android:name="android.hardware.sensor.stepcounter"
android:required="true" />
<uses-feature
android:name="android.hardware.sensor.stepdetector"
android: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;
}功能使用
private boolean isBind = false;
private Messenger mGetReplyMessenger = new Messenger(new Handler(this));
private Messenger messenger;
/**
* 开启计步服务
*/
private void setupService() {
Intent intent = new Intent(this, StepService.class);
isBind = bindService(intent, conn, Context.BIND_AUTO_CREATE);
startService(intent);
}
/**
* 从service服务中拿到步数
*
* @param msg
* @return
*/
@Override
public boolean handleMessage(Message msg) {
switch (msg.what) {
case Constant.MSG_FROM_SERVER:
cc.setCurrentCount(10000, msg.getData().getInt("step"));
break;
}
return false;
}
/**
* 用于查询应用服务(application Service)的状态的一种interface,
* 更详细的信息可以参考Service 和 context.bindService()中的描述,
* 和许多来自系统的回调方式一样,ServiceConnection的方法都是进程的主线程中调用的。
*/
ServiceConnection conn = new ServiceConnection() {
/**
* 在建立起于Service的连接时会调用该方法,目前Android是通过IBind机制实现与服务的连接。
* @param name 实际所连接到的Service组件名称
* @param service 服务的通信信道的IBind,可以通过Service访问对应服务
*/
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
try {
messenger = new Messenger(service);
Message msg = Message.obtain(null, Constant.MSG_FROM_CLIENT);
msg.replyTo = mGetReplyMessenger;
messenger.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
}
/**
* 当与Service之间的连接丢失的时候会调用该方法,
* 这种情况经常发生在Service所在的进程崩溃或者被Kill的时候调用,
* 此方法不会移除与Service的连接,当服务重新启动的时候仍然会调用 onServiceConnected()。
* @param name 丢失连接的组件名称
*/
@Override
public void onServiceDisconnected(ComponentName name) {
}
};效果展示


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效果展示

相关推荐
xfcyhades 2020-11-20
Michael 2020-11-03
业余架构师 2020-10-09
OuNuo0 2020-09-29
moses 2020-09-22
Angelia 2020-09-11
qinxu 2020-09-10
刘炳昭 2020-09-10
Nostalgiachild 2020-09-07
Nostalgiachild 2020-08-17
leavesC 2020-08-14
一青年 2020-08-13
AndroidAiStudy 2020-08-07
ydc0 2020-07-30
绿豆饼 2020-07-28