应用主要是实现记步功能,可以比较准确的显示出步数。

1、在启动应用的时候先初始化ui和启动线程,在线程里更新步数。然后启动Service。

package com.example.pedometer;import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Handler.Callback;
import android.os.Message;
import android.os.Messenger;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.util.Log;
import android.widget.TextView;public class MainActivity extends Activity implements Callback {private static final String TAG="nsc";public static final int MSG_FROM_CLIENT = 0;public static final int MSG_FROM_SERVER = 1;//返回服务public static final int REQUEST_SERVER = 2;//取消服务private long TIME_INTERVAL = 500;private TextView text;private Handler delayHandler;private Messenger messenger;private Messenger mGetReplyMessenger = new Messenger(new Handler(this));ServiceConnection conn = new ServiceConnection() {@Overridepublic void onServiceDisconnected(ComponentName arg0) {// TODO Auto-generated method stub} @Overridepublic void onServiceConnected(ComponentName name, IBinder service) {// TODO Auto-generated method stubtry{messenger = new Messenger(service);Message msg = Message.obtain(null,MSG_FROM_CLIENT);msg.replyTo = mGetReplyMessenger;//replyTo消息管理器Log.d(TAG,"msg ="+ msg);messenger.send(msg);//发送消息出去}catch(Exception e){e.printStackTrace();}}};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);initUI();//初始化ui和启动线程setupService();//启动服务}/*** 启动服务*/private void setupService() {// TODO Auto-generated method stubIntent intent = new Intent(this,StepService.class);//使用这个ServiceConnection,客户端可以绑定到一个service,通过把它传给bindService()//第一个bindService()的参数是一个明确指定了要绑定的service的Intent.//第二个参数是ServiceConnection对象.//第三个参数是一个标志,它表明绑定中的操作.它一般应是BIND_AUTO_CREATE,这样就会在service不存在时创建一个.其它可选的值是BIND_DEBUG_UNBIND和BIND_NOT_FOREGROUND,不想指定时设为0即可.。bindService(intent, conn, BIND_AUTO_CREATE);//BIND_AUTO_CREATE =1startService(intent);}private void initUI() {// TODO Auto-generated method stubtext = (TextView)findViewById(R.id.text);delayHandler = new Handler(this);}@Overridepublic boolean handleMessage(Message msg) {// TODO Auto-generated method stubswitch(msg.what){case MSG_FROM_SERVER:Log.d(TAG,"text="+ msg.getData().getInt("step"));text.setText(msg.getData().getInt("step")+"");//显示记步数//延时500ms发送值为REQUEST_SERVER 消息delayHandler.sendEmptyMessageDelayed(REQUEST_SERVER, TIME_INTERVAL);break;case REQUEST_SERVER:try{Message message = Message.obtain(null,MSG_FROM_CLIENT);//发送消息message.replyTo = mGetReplyMessenger;Log.d(TAG,"message="+ message);messenger.send(message);}catch(Exception e){e.printStackTrace();}break;}return false;}@Overrideprotected void onDestroy() {// TODO Auto-generated method stubsuper.onDestroy();unbindService(conn);//解除服务的绑定}}

代码布局:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:paddingBottom="@dimen/activity_vertical_margin"android:paddingLeft="@dimen/activity_horizontal_margin"android:paddingRight="@dimen/activity_horizontal_margin"android:paddingTop="@dimen/activity_vertical_margin"android:background="@drawable/aa"tools:context=".MainActivity" ><TextViewandroid:id="@+id/text"android:layout_width="wrap_content"android:layout_height="wrap_content"android:textColor="#000000"android:layout_centerInParent="true"android:textSize="100sp"/></RelativeLayout>

2、StepService.java 代码:

package com.example.pedometer;import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Intent;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.util.Log;public class StepService extends Service implements SensorEventListener {private final static String TAG="SetpService";private SensorManager sensorManager;private StepDcretor stepDetector;private BroadcastReceiver mBroadcastReceiver;private final static int MSG=0;private final static int MSG_SERVER=1;//计步器传感器类型 0-counter 1-detectorprivate static int stepSensor = -1;private Messenger messenger = new Messenger(new MessenerHandler());private static class MessenerHandler extends Handler{@Overridepublic void handleMessage(Message msg) {// TODO Auto-generated method stubswitch(msg.what){case MSG:try{Messenger messenger = msg.replyTo;Message replyMsg = Message.obtain(null, MSG_SERVER);Bundle bundle = new Bundle();bundle.putInt("step", StepDcretor.CURRENT_SETP);replyMsg.setData(bundle);Log.d(TAG, replyMsg+"");messenger.send(replyMsg);}catch(Exception e){e.printStackTrace();}break;default:super.handleMessage(msg);  }       }}@Overridepublic IBinder onBind(Intent intent) {// TODO Auto-generated method stubreturn messenger.getBinder();}@Override@Deprecatedpublic void onStart(Intent intent, int startId) {// TODO Auto-generated method stubsuper.onStart(intent, startId);}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {// TODO Auto-generated method stubreturn START_STICKY;}private void startStepDetector(){if(sensorManager != null && stepDetector !=null){sensorManager.unregisterListener(stepDetector);sensorManager = null;stepDetector = null;}//getLock(this);//获取传感器管理器的实例sensorManager = (SensorManager)this.getSystemService(SENSOR_SERVICE);//android 4.4以后可以使用计步传感器  在根据API不同版本分别执行addCountStepListener和addBasePedoListener两个方法int VERSION_CODES = android.os.Build.VERSION.SDK_INT;Log.d(TAG, VERSION_CODES+"");if(VERSION_CODES>19){//sdk版本addCountStepListener();}else{addBasePedoListener();}}private void addBasePedoListener() {// TODO Auto-generated method stubstepDetector = new StepDcretor(this);// 获得传感器的类型,这里获得的类型是加速度传感器// 此方法用来注册,只有注册过才会生效,参数:SensorEventListener的实例,Sensor的实例,更新速率Sensor sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);// sensorManager.unregisterListener(stepDetector);sensorManager.registerListener(stepDetector, sensor,SensorManager.SENSOR_DELAY_UI);stepDetector.setOnSensorChangeListener(new StepDcretor.OnSensorChangeListener() {@Overridepublic void onChange() {// updateNotification("今日步数:" + StepDcretor.CURRENT_SETP + " 步");}});}private void addCountStepListener() {// TODO Auto-generated method stub//android 两种计步方式 detector启动后,确认了,才启动counter.Sensor detectorSensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_DETECTOR);//计步传感器Sensor countSensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER);//步行检测传感器if (countSensor != null) {stepSensor = 0;Log.v("base", "countSensor");//第一个参数是Listener,第二个参数是所得传感器类型,第三个参数值获取传感器信息的频率sensorManager.registerListener(StepService.this, countSensor, SensorManager.SENSOR_DELAY_UI);} else if (detectorSensor != null) {stepSensor = 1;Log.v("base", "detector");sensorManager.registerListener(StepService.this, detectorSensor, SensorManager.SENSOR_DELAY_UI);} else {Log.v("xf", "Count sensor not available!");addBasePedoListener();}}@Overridepublic void onSensorChanged(SensorEvent event) {// TODO Auto-generated method stubif(stepSensor ==0){StepDcretor.CURRENT_SETP = (int)event.values[0];}else if(stepSensor ==1){StepDcretor.CURRENT_SETP++;}//updateNotification("今日步数:" + StepDcretor.CURRENT_SETP + " 步");}@Overridepublic void onCreate() {// TODO Auto-generated method stubsuper.onCreate();//这里开启了一个线程,因为后台服务也是在主线程中进行,这样可以安全点,防止主线程阻塞new Thread(new Runnable() {@Overridepublic void run() {// TODO Auto-generated method stubstartStepDetector();}}).start();}@Overridepublic void onDestroy() {// TODO Auto-generated method stubunregisterReceiver(mBroadcastReceiver);//注销广播Intent intent = new Intent(this,StepService.class);startService(intent);//重新启动StepService 服务super.onDestroy();}@Overridepublic boolean onUnbind(Intent intent) {// TODO Auto-generated method stubreturn super.onUnbind(intent);}@Overridepublic void onAccuracyChanged(Sensor arg0, int arg1) {// TODO Auto-generated method stub}}

3、StepDcretor.java是记步算法的实现,详细可看代码。

package com.example.pedometer;import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.os.CountDownTimer;
import android.util.Log;import java.util.Timer;
import java.util.TimerTask;public class StepDcretor implements SensorEventListener {//存放三轴数据float[] oriValues = new float[3];final int valueNum = 4;//用于存放计算阈值的波峰波谷差值float[] tempValue = new float[valueNum];int tempCount = 0;//是否上升的标志位boolean isDirectionUp = false;//持续上升次数int continueUpCount = 0;//上一点的持续上升的次数,为了记录波峰的上升次数int continueUpFormerCount = 0;//上一点的状态,上升还是下降boolean lastStatus = false;//波峰值float peakOfWave = 0;//波谷值float valleyOfWave = 0;//此次波峰的时间long timeOfThisPeak = 0;//上次波峰的时间long timeOfLastPeak = 0;//当前的时间long timeOfNow = 0;//当前传感器的值float gravityNew = 0;//上次传感器的值float gravityOld = 0;//动态阈值需要动态的数据,这个值用于这些动态数据的阈值final float initialValue = (float) 1.7;//初始阈值float ThreadValue = (float) 2.0;private final String TAG = "StepDcretor";// alpha 由 t / (t + dT)计算得来,其中 t 是低通滤波器的时间常数,dT 是事件报送频率
//    private final float alpha = 0.8f;
//    private long perCalTime = 0;
//
//    //最新修改的精度值
//    private final float minValue = 9.8f;
//    private final float maxValue = 9.9f;
//    //9.5f
//    private final float verminValue = 8.5f;
//    //10.0f
//    private final float vermaxValue = 11.5f;
//    private final float minTime = 150;
//    private final float maxTime = 2000;/*** 0-准备计时   1-计时中  2-准备为正常计步计时  3-正常计步中*/private int CountTimeState = 0;public static int CURRENT_SETP = 0;public static int TEMP_STEP = 0;private int lastStep = -1;// 加速计的三个维度数值public static float[] gravity = new float[3];public static float[] linear_acceleration = new float[3];//用三个维度算出的平均值public static float average = 0;private Timer timer;// 倒计时4秒,4秒内不会显示计步,用于屏蔽细微波动private long duration = 4000;private TimeCount time;OnSensorChangeListener onSensorChangeListener;public interface OnSensorChangeListener {void onChange();}public StepDcretor(Context context) {super();}public void onAccuracyChanged(Sensor arg0, int arg1) {}public OnSensorChangeListener getOnSensorChangeListener() {return onSensorChangeListener;}public void setOnSensorChangeListener(OnSensorChangeListener onSensorChangeListener) {this.onSensorChangeListener = onSensorChangeListener;}public void onSensorChanged(SensorEvent event) {Sensor sensor = event.sensor;synchronized (this) {if (sensor.getType() == Sensor.TYPE_ACCELEROMETER) {calc_step(event);}}}/*** 获取传感器xyz值 然后传入  DetectorNewStep* @param event*/synchronized private void calc_step(SensorEvent event) {average = (float) Math.sqrt(Math.pow(event.values[0], 2)+ Math.pow(event.values[1], 2) + Math.pow(event.values[2], 2));DetectorNewStep(average);}/** 检测步子,并开始计步* 1.传入sersor中的数据* 2.如果检测到了波峰,并且符合时间差以及阈值的条件,则判定为1步* 3.符合时间差条件,波峰波谷差值大于initialValue,则将该差值纳入阈值的计算中* */public void DetectorNewStep(float values) {if (gravityOld == 0) {gravityOld = values;} else {if (DetectorPeak(values, gravityOld)) {timeOfLastPeak = timeOfThisPeak;timeOfNow = System.currentTimeMillis();if (timeOfNow - timeOfLastPeak >= 200&& (peakOfWave - valleyOfWave >= ThreadValue) && timeOfNow - timeOfLastPeak <= 2000) {timeOfThisPeak = timeOfNow;//更新界面的处理,不涉及到算法preStep();}if (timeOfNow - timeOfLastPeak >= 200&& (peakOfWave - valleyOfWave >= initialValue)) {timeOfThisPeak = timeOfNow;ThreadValue = Peak_Valley_Thread(peakOfWave - valleyOfWave);}}}gravityOld = values;}/****/private void preStep() {if (CountTimeState == 0) {// 开启计时器time = new TimeCount(duration, 700);time.start();CountTimeState = 1;Log.v(TAG, "开启计时器");} else if (CountTimeState == 1) {TEMP_STEP++;Log.v(TAG, "计步中 TEMP_STEP:" + TEMP_STEP);} else if (CountTimeState == 3) {CURRENT_SETP++;if (onSensorChangeListener != null) {onSensorChangeListener.onChange();}}}/** 检测波峰* 以下四个条件判断为波峰:* 1.目前点为下降的趋势:isDirectionUp为false* 2.之前的点为上升的趋势:lastStatus为true* 3.到波峰为止,持续上升大于等于2次* 4.波峰值大于1.2g,小于2g* 记录波谷值* 1.观察波形图,可以发现在出现步子的地方,波谷的下一个就是波峰,有比较明显的特征以及差值* 2.所以要记录每次的波谷值,为了和下次的波峰做对比* */public boolean DetectorPeak(float newValue, float oldValue) {lastStatus = isDirectionUp;if (newValue >= oldValue) {isDirectionUp = true;continueUpCount++;} else {continueUpFormerCount = continueUpCount;//记住上升次数,如果下降则清零continueUpCount = 0;isDirectionUp = false;}if (!isDirectionUp && lastStatus&& (continueUpFormerCount >= 2 && (oldValue >= 11.76 && oldValue < 19.6))) {peakOfWave = oldValue;//算出波峰值return true;} else if (!lastStatus && isDirectionUp) {valleyOfWave = oldValue;return false;} else {return false;}}/** 阈值的计算* 1.通过波峰波谷的差值计算阈值* 2.记录4个值,存入tempValue[]数组中* 3.在将数组传入函数averageValue中计算阈值* */public float Peak_Valley_Thread(float value) {float tempThread = ThreadValue;if (tempCount < valueNum) {tempValue[tempCount] = value;tempCount++;} else {tempThread = averageValue(tempValue, valueNum);for (int i = 1; i < valueNum; i++) {tempValue[i - 1] = tempValue[i];}tempValue[valueNum - 1] = value;}return tempThread;}/** 梯度化阈值* 1.计算数组的均值* 2.通过均值将阈值梯度化在一个范围里* */public float averageValue(float value[], int n) {float ave = 0;for (int i = 0; i < n; i++) {ave += value[i];}ave = ave / valueNum;if (ave >= 8)ave = (float) 4.3;else if (ave >= 7 && ave < 8)ave = (float) 3.3;else if (ave >= 4 && ave < 7)ave = (float) 2.3;else if (ave >= 3 && ave < 4)ave = (float) 2.0;else {ave = (float) 1.3;}return ave;}class TimeCount extends CountDownTimer {public TimeCount(long millisInFuture, long countDownInterval) {super(millisInFuture, countDownInterval);}@Overridepublic void onFinish() {// 如果计时器正常结束,则开始计步time.cancel();CURRENT_SETP += TEMP_STEP;lastStep = -1;
//            CountTimeState = 2;Log.v(TAG, "计时正常结束");timer = new Timer(true);TimerTask task = new TimerTask() {public void run() {if (lastStep == CURRENT_SETP) {timer.cancel();CountTimeState = 0;lastStep = -1;TEMP_STEP = 0;Log.v(TAG, "停止计步:" + CURRENT_SETP);} else {lastStep = CURRENT_SETP;}}};timer.schedule(task, 0, 3000);CountTimeState = 3;//正常记步}@Overridepublic void onTick(long millisUntilFinished) {if (lastStep == TEMP_STEP) {Log.v(TAG, "onTick 计时停止");time.cancel();CountTimeState = 0;lastStep = -1;TEMP_STEP = 0;} else {lastStep = TEMP_STEP;}}}//废弃的算法//    private void oldCalStep(SensorEvent event) {
//        // 用低通滤波器分离出重力加速度
//        gravity[0] = alpha * gravity[0] + (1 - alpha) * event.values[0];
//        gravity[1] = alpha * gravity[1] + (1 - alpha) * event.values[1];
//        gravity[2] = alpha * gravity[2] + (1 - alpha) * event.values[2];
//
//        average = (float) Math.sqrt(Math.pow(gravity[0], 2)
//                + Math.pow(gravity[1], 2) + Math.pow(gravity[2], 2));
//
//        if (average <= minValue) {
//            Log.v("xfblog", "低");
//            perCalTime = System.currentTimeMillis();
//        }
//        else if (average >= maxValue) {
//            Log.v("xfblog", "高");
//            float betweentime = System.currentTimeMillis()
//                    - perCalTime;
//            if (betweentime >= minTime && betweentime < maxTime) {
//                perCalTime = 0;
//                if (CountTimeState == 0) {
//                    // 开启计时器
//                    time = new TimeCount(duration, 800);
//                    time.start();
//                    CountTimeState = 1;
//                    Log.v(TAG, "开启计时器");
//                } else if (CountTimeState == 1) {
//                    TEMP_STEP++;
//                    Log.v(TAG, "计步中 TEMP_STEP:" + TEMP_STEP);
//                }
//                else if (CountTimeState == 3) {
//                    CURRENT_SETP++;
//                    if (onSensorChangeListener != null) {
//                        onSensorChangeListener.onChange();
//                    }
//                }
//
//
//            }
//        }
//    }
}

4、权限代码:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.example.pedometer"android:versionCode="1"android:versionName="1.0" ><uses-sdkandroid:minSdkVersion="8"android:targetSdkVersion="18" /><uses-permission android:name="android.permission.WAKE_LOCK" /><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.WRITE_EXTERNAL_STORAGE"/><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/><applicationandroid:allowBackup="true"android:icon="@drawable/ic_launcher"android:label="@string/app_name"android:theme="@style/AppTheme" ><activityandroid:name="com.example.pedometer.MainActivity"android:label="@string/app_name" ><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity><serviceandroid:name="com.example.pedometer.StepService"android:process="com.example.pedometer.step"android:priority="1000"><intent-filter ><!-- 系统启动完成后会调用--><action android:name="android.intent.action.BOOT_COMPLETED"/><action android:name="android.intent.action.DATE_CHANGED"/><action android:name="android.intent.action.MEDIA_MOUNTED" /><action android:name="android.intent.action.USER_PRESENT" /><action android:name="android.intent.action.ACTION_TIME_TICK" /><action android:name="android.intent.action.ACTION_POWER_CONNECTED" /><action android:name="android.intent.action.ACTION_POWER_DISCONNECTED" /></intent-filter></service></application></manifest>

此算法为网上看到的,裁剪了部分不需要的代码,代码下载:点击打开链接

android 计步器代码(prdometer)相关推荐

  1. android 计步器 开发,Android计步器开发

    本文只赘述Android计步器开发里计步的原理. 在Android4.4版本之后,新增了STEP_COUNTER和STEP_DECTECTOR STEP_COUNTER表示自从开机以来,你走的步数累计 ...

  2. Android计步器算法实现

    最近在研究惯性导航和其他导航算法的融合,顺手把计步.步长等一堆算法写成类了,舒服~ 这篇文章我不会具体的讲解实现原理,有兴趣研究的朋友直接看我写的计步算法实现和步长计算. Android系统有自带的计 ...

  3. Android计步器的实现(1)

    最近项目中要加一个计步器的功能,Github上搜索一堆,都是bug漫天飞(微信也有bug^_^,关于bug的原因有:异常开关机.调整手机时间. 正常开关机.跨天问题,这几种原因复合在一起更容易造成计步 ...

  4. 160多个android开源代码汇总

    CreditsRoll 类似星球大战字幕效果的TextView 项目地址:https://github.com/frakbot/CreditsRoll android-process-buton 带加 ...

  5. Android计步器的实现(2)

    上一篇见: Android计步器的实现(1) 2.时间戳工具 public abstract class Util4Pedometer {/*** @return milliseconds since ...

  6. Android计步器小Demo

    描述 android计步器的实现,自定义的一个弧形进度条,记步通过手机的传感器来实现,也就是说不支持传感器的机子(应该很老的了吧)就没有效果.看看效果图: 自定义View public class S ...

  7. android 计步器

    我们经常会看到微信 QQ 以及其他一些运动app里面都有一个计步功能,那它是怎么实现的呢? 今天我们就来实现一下,以下代码都是从一个整体项目中抽离出来的,为了理解简单方便我把UI部分数据保存部分全部都 ...

  8. UI福利包——160多个android开源代码汇总

    查看原文出处 第一部分 个性化控件(View) 主要介绍那些不错个性化的View,包括ListView.ActionBar.Menu.ViewPager.Gallery.GridView.ImageV ...

  9. android命令行工具 混淆,Android 混淆代码学习以及Android加密工具--APKProtect的使用ZZ...

    一:情景分析 有时候看到其他应用App的一些效果很炫,或者是功能实现很好就想着参考参考,于是乎,下载APK----反编译APK---查看源码....,但是悲剧来了....源码都是些a,b,c...等等 ...

最新文章

  1. Spring 5.1.13 和 Spring Boot 2.2.3 发布
  2. 【2017-11-26】Linq表连接查询
  3. 在 GridView 控件中添加一列复选框51
  4. CCCatmullRomBy和CCPointArray
  5. Replace Delegation with Inheritance(以继承取代委托)
  6. 公司的个性制度与团队精神
  7. A[1080]Graduate Admission 两个cmp比较函数两个struct结构体
  8. AWS亚马逊服务器配置过程
  9. OL3实现空间查询的代码示例
  10. Smartphone--Android真机管理平台
  11. poi生成excel整理(设置边框/字体/颜色/加粗/居中/)
  12. 杭电1856——并差集
  13. python工具类-selenium 浏览器封装
  14. cython,加速python,保护代码(3):扩展文件 .pxd
  15. 好书读不完,常存常读常更新
  16. MVG学习笔记(10) --射影变换的初步了解
  17. vb.net控件随窗口大小调整
  18. 阿里,字节,拼多多,B站挨个面试一遍,你们猜哪个待遇最高?
  19. 教程 | 零代码复制网页房源信息至表格中
  20. onvif gsoap 设备端接口方法部署示例及gsoap代码调用分析

热门文章

  1. 钉钉第三方企业应用,获取用户信息
  2. 颜值与实力结合体 全新一代K3不容小觑
  3. 如何利用计算机漏洞,担心电脑被人利用“CPU漏洞”攻击?这里有一份简单的指南...
  4. luoguP4921 情侣?给我烧了!
  5. 华为OD机试真题 Java 实现【任务调度】【2022.11 Q4 新题】
  6. 题解——7-4 圈点
  7. C++内存管理+模板入门知识点
  8. 空瓶换汽水(三个空瓶换一个汽水,n个空瓶能换多少个汽水)
  9. gt2pro搭载鸿蒙系统,首款鸿蒙系统智能手表华为Watch GT2 Pro还能这么玩!
  10. 三个字组成的字,学习一下