Android之指南针

来源:互联网 发布:js dom编程艺术 编辑:程序博客网 时间:2024/04/28 15:41
 点我下载源码

       今天,在小米的开源项目中下载了一个指南针源码学习了一下,感觉不仅界面做得很漂亮,代码也是很精致,所以我在研究了之后,加了比较多的注释,果断跟大家分享一下,很精简的几段代码,仔细品味可以学到很多东西,我稍微总结一下:

①.handler的灵活运用,每20秒后执行一次自己,用来检测方向变化值,更新指南针旋转。

②.传感器和谷歌位置服务的使用。

③.自定义View,这里面是自定义一个ImageView,自己增加一个旋转图片的方法。

④.Android动画Interpolator插入器:AccelerateInterpolator加速插入器的运用。顺便说一下另外几个插入器:

                                     ——AccelerateInterpolator:动画从开始到结束,变化率是一个加速的过程。

                                     ——DecelerateInterpolator:动画从开始到结束,变化率是一个减速的过程。

                                     ——CycleInterpolator:动画从开始到结束,变化率是循环给定次数的正弦曲线。

                                   ——AccelerateDecelerateInterpolator:动画从开始到结束,变化率是先加速后减速的过程。

                                    ——LinearInterpolator:动画从开始到结束,变化率是线性变化。
                                    AccelerateInterpolator有一个方法:getInterpolation(float input);

⑤.巧妙的数字替换成对应的数字图片和根据本地语言使用对应的图片资源(图片资源国际化,哈哈)。还有一些其他的小知识,朋友们,自己下载去研究吧!

下面看一下效果图(我的是模拟器,木有传感器也木有定位的):

下面我们来看一下这个界面的布局文件(main.xml):

[html] view plaincopyprint?
  1. <?xmlversion="1.0"encoding="UTF-8"?> 
  2. <FrameLayoutxmlns:android="http://schemas.android.com/apk/res/android" 
  3.     android:layout_width="fill_parent" 
  4.     android:layout_height="fill_parent"> 
  5.  
  6.     <FrameLayout 
  7.         android:layout_width="fill_parent" 
  8.         android:layout_height="fill_parent" 
  9.         android:background="@drawable/background"> 
  10.  
  11.         <LinearLayout 
  12.             android:id="@+id/view_compass" 
  13.             android:layout_width="fill_parent" 
  14.             android:layout_height="fill_parent" 
  15.             android:background="@drawable/background_light" 
  16.             android:orientation="vertical"> 
  17.  
  18.             <LinearLayout 
  19.                 android:layout_width="fill_parent" 
  20.                 android:layout_height="0dip" 
  21.                 android:layout_weight="1" 
  22.                 android:orientation="vertical"> 
  23.  
  24.                 <FrameLayout 
  25.                     android:layout_width="fill_parent" 
  26.                     android:layout_height="wrap_content" 
  27.                     android:background="@drawable/prompt"> 
  28.  
  29.                     <LinearLayout 
  30.                         android:layout_width="fill_parent" 
  31.                         android:layout_height="wrap_content" 
  32.                         android:layout_gravity="center_horizontal" 
  33.                         android:layout_marginTop="70dip" 
  34.                         android:orientation="horizontal"> 
  35.  
  36.                         <LinearLayout 
  37.                             android:id="@+id/layout_direction" 
  38.                             android:layout_width="0dip" 
  39.                             android:layout_height="wrap_content" 
  40.                             android:layout_weight="1" 
  41.                             android:gravity="right" 
  42.                             android:orientation="horizontal"> 
  43.                         </LinearLayout> 
  44.  
  45.                         <ImageView 
  46.                             android:layout_width="20dip" 
  47.                             android:layout_height="fill_parent"> 
  48.                         </ImageView> 
  49.  
  50.                         <LinearLayout 
  51.                             android:id="@+id/layout_angle" 
  52.                             android:layout_width="0dip" 
  53.                             android:layout_height="wrap_content" 
  54.                             android:layout_weight="1" 
  55.                             android:gravity="left" 
  56.                             android:orientation="horizontal"> 
  57.                         </LinearLayout> 
  58.                     </LinearLayout> 
  59.                 </FrameLayout> 
  60.  
  61.                 <LinearLayout 
  62.                     android:layout_width="fill_parent" 
  63.                     android:layout_height="0dip" 
  64.                     android:layout_weight="1" 
  65.                     android:orientation="vertical"> 
  66.  
  67.                     <FrameLayout 
  68.                         android:layout_width="fill_parent" 
  69.                         android:layout_height="wrap_content" 
  70.                         android:layout_gravity="center"> 
  71.  
  72.                         <ImageView 
  73.                             android:layout_width="wrap_content" 
  74.                             android:layout_height="wrap_content" 
  75.                             android:layout_gravity="center" 
  76.                             android:src="@drawable/background_compass"/> 
  77.  
  78.                         <net.micode.compass.CompassView 
  79.                             android:id="@+id/compass_pointer" 
  80.                             android:layout_width="wrap_content" 
  81.                             android:layout_height="wrap_content" 
  82.                             android:layout_gravity="center" 
  83.                             android:src="@drawable/compass"/> 
  84.  
  85.                         <ImageView 
  86.                             android:layout_width="wrap_content" 
  87.                             android:layout_height="wrap_content" 
  88.                             android:layout_gravity="center" 
  89.                             android:src="@drawable/miui_cover"/> 
  90.                     </FrameLayout> 
  91.                 </LinearLayout> 
  92.             </LinearLayout> 
  93.  
  94.             <FrameLayout 
  95.                 android:id="@+id/location_layout" 
  96.                 android:layout_width="fill_parent" 
  97.                 android:layout_height="wrap_content"> 
  98.  
  99.                 <LinearLayout 
  100.                     android:layout_width="fill_parent" 
  101.                     android:layout_height="wrap_content" 
  102.                     android:background="@drawable/background_bottom" 
  103.                     android:orientation="vertical"> 
  104.                 </LinearLayout> 
  105.  
  106.                 <TextView 
  107.                     android:id="@+id/textview_location" 
  108.                     android:layout_width="wrap_content" 
  109.                     android:layout_height="wrap_content" 
  110.                     android:layout_gravity="center" 
  111.                     android:text="@string/getting_location" 
  112.                     android:textAppearance="?android:attr/textAppearanceMedium" 
  113.                     android:textColor="#7FFFFFFF"/> 
  114.             </FrameLayout> 
  115.         </LinearLayout> 
  116.     </FrameLayout> 
  117.  
  118. </FrameLayout> 


这其中用到了一个自定义view,其实就是中间那个可以旋转的指南针,我们也来看看它的代码(CompassView.java):

[java] view plaincopyprint?
  1. /**
  2. * 自定义一个View继承ImageView,增加一个通用的旋转图片资源的方法
  3. *
  4. * @author way
  5. *
  6. */ 
  7. public class CompassViewextends ImageView { 
  8.     private float mDirection;// 方向旋转浮点数 
  9.     private Drawable compass;// 图片资源 
  10.      
  11.     //三个构造器 
  12.     public CompassView(Context context) { 
  13.         super(context); 
  14.         mDirection = 0.0f;// 默认不旋转 
  15.         compass = null
  16.     } 
  17.  
  18.     public CompassView(Context context, AttributeSet attrs) { 
  19.         super(context, attrs); 
  20.         mDirection = 0.0f; 
  21.         compass = null
  22.     } 
  23.  
  24.     public CompassView(Context context, AttributeSet attrs,int defStyle) { 
  25.         super(context, attrs, defStyle); 
  26.         mDirection = 0.0f; 
  27.         compass = null
  28.     } 
  29.  
  30.     @Override 
  31.     protected void onDraw(Canvas canvas) { 
  32.         if (compass == null) { 
  33.             compass = getDrawable();// 获取当前view的图片资源 
  34.             compass.setBounds(0, 0, getWidth(), getHeight());// 图片资源在view的位置,此处相当于充满view 
  35.         } 
  36.  
  37.         canvas.save(); 
  38.         canvas.rotate(mDirection, getWidth() / 2, getHeight() /2);// 绕图片中心点旋转, 
  39.         compass.draw(canvas);// 把旋转后的图片画在view上,即保持旋转后的样子 
  40.         canvas.restore();// 保存一下 
  41.     } 
  42.  
  43.     /**
  44.      * 自定义更新方向的方法
  45.      *
  46.      * @param direction
  47.      *            传入的方向
  48.      */ 
  49.     public void updateDirection(float direction) { 
  50.         mDirection = direction; 
  51.         invalidate();// 重新刷新一下,更新方向 
  52.     } 
  53.  


接下来就只剩下一个Activity了,其实总体结构还是很简单的,CompassActivity.java:

[java] view plaincopyprint?
  1. /**
  2. * MainActivity
  3. *
  4. * @author way
  5. *
  6. */ 
  7. public class CompassActivityextends Activity { 
  8.     private staticfinal int EXIT_TIME =2000;// 两次按返回键的间隔判断 
  9.     private finalfloat MAX_ROATE_DEGREE = 1.0f;// 最多旋转一周,即360° 
  10.     private SensorManager mSensorManager;// 传感器管理对象 
  11.     private Sensor mOrientationSensor;// 传感器对象 
  12.     private LocationManager mLocationManager;// 位置管理对象 
  13.     private String mLocationProvider;// 位置提供者名称,GPS设备还是网络 
  14.     private float mDirection;// 当前浮点方向 
  15.     private float mTargetDirection;// 目标浮点方向 
  16.     private AccelerateInterpolator mInterpolator;// 动画从开始到结束,变化率是一个加速的过程,就是一个动画速率 
  17.     protected final Handler mHandler =new Handler(); 
  18.     private boolean mStopDrawing;// 是否停止指南针旋转的标志位 
  19.     private boolean mChinease;// 系统当前是否使用中文 
  20.     private long firstExitTime = 0L;// 用来保存第一次按返回键的时间 
  21.  
  22.     View mCompassView; 
  23.     CompassView mPointer;// 指南针view 
  24.     TextView mLocationTextView;// 显示位置的view 
  25.     LinearLayout mDirectionLayout;// 显示方向(东南西北)的view 
  26.     LinearLayout mAngleLayout;// 显示方向度数的view 
  27.  
  28.     // 这个是更新指南针旋转的线程,handler的灵活使用,每20毫秒检测方向变化值,对应更新指南针旋转 
  29.     protected Runnable mCompassViewUpdater =new Runnable() { 
  30.         @Override 
  31.         public void run() { 
  32.             if (mPointer != null && !mStopDrawing) { 
  33.                 if (mDirection != mTargetDirection) { 
  34.  
  35.                     // calculate the short routine 
  36.                     float to = mTargetDirection; 
  37.                     if (to - mDirection >180) { 
  38.                         to -= 360
  39.                     } elseif (to - mDirection < -180) { 
  40.                         to += 360
  41.                     } 
  42.  
  43.                     // limit the max speed to MAX_ROTATE_DEGREE 
  44.                     float distance = to - mDirection; 
  45.                     if (Math.abs(distance) > MAX_ROATE_DEGREE) { 
  46.                         distance = distance > 0 ? MAX_ROATE_DEGREE 
  47.                                 : (-1.0f * MAX_ROATE_DEGREE); 
  48.                     } 
  49.  
  50.                     // need to slow down if the distance is short 
  51.                     mDirection = normalizeDegree(mDirection 
  52.                             + ((to - mDirection) * mInterpolator 
  53.                                     .getInterpolation(Math.abs(distance) > MAX_ROATE_DEGREE ?0.4f 
  54.                                             : 0.3f)));// 用了一个加速动画去旋转图片,很细致 
  55.                     mPointer.updateDirection(mDirection);// 更新指南针旋转 
  56.                 } 
  57.  
  58.                 updateDirection();// 更新方向值 
  59.  
  60.                 mHandler.postDelayed(mCompassViewUpdater, 20);// 20毫米后重新执行自己,比定时器好 
  61.             } 
  62.         } 
  63.     }; 
  64.  
  65.     @Override 
  66.     protected void onCreate(Bundle savedInstanceState) { 
  67.         super.onCreate(savedInstanceState); 
  68.         setContentView(R.layout.main); 
  69.         initResources();// 初始化view 
  70.         initServices();// 初始化传感器和位置服务 
  71.     } 
  72.  
  73.     @Override 
  74.     public void onBackPressed() {// 覆盖返回键 
  75.         long curTime = System.currentTimeMillis(); 
  76.         if (curTime - firstExitTime < EXIT_TIME) {// 两次按返回键的时间小于2秒就退出应用 
  77.             finish(); 
  78.         } else
  79.             Toast.makeText(this, R.string.exit_toast, Toast.LENGTH_SHORT) 
  80.                     .show(); 
  81.             firstExitTime = curTime; 
  82.         } 
  83.     } 
  84.  
  85.     @Override 
  86.     protected void onResume() {// 在恢复的生命周期里判断、启动位置更新服务和传感器服务 
  87.         super.onResume(); 
  88.         if (mLocationProvider != null) { 
  89.             updateLocation(mLocationManager 
  90.                     .getLastKnownLocation(mLocationProvider)); 
  91.             mLocationManager.requestLocationUpdates(mLocationProvider,2000
  92.                     10, mLocationListener);// 2秒或者距离变化10米时更新一次地理位置 
  93.         } else
  94.             mLocationTextView.setText(R.string.cannot_get_location); 
  95.         } 
  96.         if (mOrientationSensor != null) { 
  97.             mSensorManager.registerListener(mOrientationSensorEventListener, 
  98.                     mOrientationSensor, SensorManager.SENSOR_DELAY_GAME); 
  99.         } else
  100.             Toast.makeText(this, R.string.cannot_get_sensor, Toast.LENGTH_SHORT) 
  101.                     .show(); 
  102.         } 
  103.         mStopDrawing = false
  104.         mHandler.postDelayed(mCompassViewUpdater, 20);// 20毫秒执行一次更新指南针图片旋转 
  105.     } 
  106.  
  107.     @Override 
  108.     protected void onPause() {// 在暂停的生命周期里注销传感器服务和位置更新服务 
  109.         super.onPause(); 
  110.         mStopDrawing = true
  111.         if (mOrientationSensor !=null) { 
  112.             mSensorManager.unregisterListener(mOrientationSensorEventListener); 
  113.         } 
  114.         if (mLocationProvider != null) { 
  115.             mLocationManager.removeUpdates(mLocationListener); 
  116.         } 
  117.     } 
  118.  
  119.     // 初始化view 
  120.     private void initResources() { 
  121.         mDirection = 0.0f;// 初始化起始方向 
  122.         mTargetDirection = 0.0f;// 初始化目标方向 
  123.         mInterpolator = new AccelerateInterpolator();// 实例化加速动画对象 
  124.         mStopDrawing = true
  125.         mChinease = TextUtils.equals(Locale.getDefault().getLanguage(),"zh");// 判断系统当前使用的语言是否为中文 
  126.  
  127.         mCompassView = findViewById(R.id.view_compass);// 实际上是一个LinearLayout,装指南针ImageView和位置TextView 
  128.         mPointer = (CompassView) findViewById(R.id.compass_pointer);// 自定义的指南针view 
  129.         mLocationTextView = (TextView) findViewById(R.id.textview_location);// 显示位置信息的TextView 
  130.         mDirectionLayout = (LinearLayout) findViewById(R.id.layout_direction);// 顶部显示方向名称(东南西北)的LinearLayout 
  131.         mAngleLayout = (LinearLayout) findViewById(R.id.layout_angle);// 顶部显示方向具体度数的LinearLayout 
  132.  
  133.         mPointer.setImageResource(mChinease ? R.drawable.compass_cn 
  134.                 : R.drawable.compass);// 如果系统使用中文,就用中文的指南针图片 
  135.     } 
  136.  
  137.     // 初始化传感器和位置服务 
  138.     private void initServices() { 
  139.         // sensor manager 
  140.         mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); 
  141.         mOrientationSensor = mSensorManager 
  142.                 .getDefaultSensor(Sensor.TYPE_ORIENTATION); 
  143.  
  144.         // location manager 
  145.         mLocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); 
  146.         Criteria criteria = new Criteria();// 条件对象,即指定条件过滤获得LocationProvider 
  147.         criteria.setAccuracy(Criteria.ACCURACY_FINE);// 较高精度 
  148.         criteria.setAltitudeRequired(false);// 是否需要高度信息 
  149.         criteria.setBearingRequired(false);// 是否需要方向信息 
  150.         criteria.setCostAllowed(true);// 是否产生费用 
  151.         criteria.setPowerRequirement(Criteria.POWER_LOW);// 设置低电耗 
  152.         mLocationProvider = mLocationManager.getBestProvider(criteria, true);// 获取条件最好的Provider 
  153.  
  154.     } 
  155.  
  156.     // 更新顶部方向显示的方法 
  157.     private void updateDirection() { 
  158.         LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT, 
  159.                 LayoutParams.WRAP_CONTENT); 
  160.         // 先移除layout中所有的view 
  161.         mDirectionLayout.removeAllViews(); 
  162.         mAngleLayout.removeAllViews(); 
  163.  
  164.         // 下面是根据mTargetDirection,作方向名称图片的处理 
  165.         ImageView east = null
  166.         ImageView west = null
  167.         ImageView south = null
  168.         ImageView north = null
  169.         float direction = normalizeDegree(mTargetDirection * -1.0f); 
  170.         if (direction > 22.5f && direction <157.5f) { 
  171.             // east 
  172.             east = new ImageView(this); 
  173.             east.setImageResource(mChinease ? R.drawable.e_cn : R.drawable.e); 
  174.             east.setLayoutParams(lp); 
  175.         } else if (direction >202.5f && direction < 337.5f) { 
  176.             // west 
  177.             west = new ImageView(this); 
  178.             west.setImageResource(mChinease ? R.drawable.w_cn : R.drawable.w); 
  179.             west.setLayoutParams(lp); 
  180.         } 
  181.  
  182.         if (direction > 112.5f && direction <247.5f) { 
  183.             // south 
  184.             south = new ImageView(this); 
  185.             south.setImageResource(mChinease ? R.drawable.s_cn : R.drawable.s); 
  186.             south.setLayoutParams(lp); 
  187.         } else if (direction <67.5 || direction > 292.5f) { 
  188.             // north 
  189.             north = new ImageView(this); 
  190.             north.setImageResource(mChinease ? R.drawable.n_cn : R.drawable.n); 
  191.             north.setLayoutParams(lp); 
  192.         } 
  193.         // 下面是根据系统使用语言,更换对应的语言图片资源 
  194.         if (mChinease) { 
  195.             // east/west should be before north/south 
  196.             if (east != null) { 
  197.                 mDirectionLayout.addView(east); 
  198.             } 
  199.             if (west != null) { 
  200.                 mDirectionLayout.addView(west); 
  201.             } 
  202.             if (south != null) { 
  203.                 mDirectionLayout.addView(south); 
  204.             } 
  205.             if (north !=null) { 
  206.                 mDirectionLayout.addView(north); 
  207.             } 
  208.         } else
  209.             // north/south should be before east/west 
  210.             if (south != null) { 
  211.                 mDirectionLayout.addView(south); 
  212.             } 
  213.             if (north !=null) { 
  214.                 mDirectionLayout.addView(north); 
  215.             } 
  216.             if (east != null) { 
  217.                 mDirectionLayout.addView(east); 
  218.             } 
  219.             if (west != null) { 
  220.                 mDirectionLayout.addView(west); 
  221.             } 
  222.         } 
  223.         // 下面是根据方向度数显示度数图片数字 
  224.         int direction2 = (int) direction; 
  225.         boolean show = false
  226.         if (direction2 >= 100) { 
  227.             mAngleLayout.addView(getNumberImage(direction2 /100)); 
  228.             direction2 %= 100
  229.             show = true
  230.         } 
  231.         if (direction2 >=10 || show) { 
  232.             mAngleLayout.addView(getNumberImage(direction2 / 10)); 
  233.             direction2 %= 10
  234.         } 
  235.         mAngleLayout.addView(getNumberImage(direction2)); 
  236.         // 下面是增加一个°的图片 
  237.         ImageView degreeImageView = new ImageView(this); 
  238.         degreeImageView.setImageResource(R.drawable.degree); 
  239.         degreeImageView.setLayoutParams(lp); 
  240.         mAngleLayout.addView(degreeImageView); 
  241.     } 
  242.  
  243.     // 获取方向度数对应的图片,返回ImageView 
  244.     private ImageView getNumberImage(int number) { 
  245.         ImageView image = new ImageView(this); 
  246.         LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT, 
  247.                 LayoutParams.WRAP_CONTENT); 
  248.         switch (number) { 
  249.         case 0
  250.             image.setImageResource(R.drawable.number_0); 
  251.             break
  252.         case 1
  253.             image.setImageResource(R.drawable.number_1); 
  254.             break
  255.         case 2
  256.             image.setImageResource(R.drawable.number_2); 
  257.             break
  258.         case 3
  259.             image.setImageResource(R.drawable.number_3); 
  260.             break
  261.         case 4
  262.             image.setImageResource(R.drawable.number_4); 
  263.             break
  264.         case 5
  265.             image.setImageResource(R.drawable.number_5); 
  266.             break
  267.         case 6
  268.             image.setImageResource(R.drawable.number_6); 
  269.             break
  270.         case 7
  271.             image.setImageResource(R.drawable.number_7); 
  272.             break
  273.         case 8
  274.             image.setImageResource(R.drawable.number_8); 
  275.             break
  276.         case 9
  277.             image.setImageResource(R.drawable.number_9); 
  278.             break
  279.         } 
  280.         image.setLayoutParams(lp); 
  281.         return image; 
  282.     } 
  283.  
  284.     // 更新位置显示 
  285.     private void updateLocation(Location location) { 
  286.         if (location == null) { 
  287.             mLocationTextView.setText(R.string.getting_location); 
  288.         } else
  289.             StringBuilder sb = new StringBuilder(); 
  290.             double latitude = location.getLatitude(); 
  291.             double longitude = location.getLongitude(); 
  292.  
  293.             if (latitude >=0.0f) { 
  294.                 sb.append(getString(R.string.location_north, 
  295.                         getLocationString(latitude))); 
  296.             } else
  297.                 sb.append(getString(R.string.location_south, 
  298.                         getLocationString(-1.0 * latitude))); 
  299.             } 
  300.  
  301.             sb.append("    "); 
  302.  
  303.             if (longitude >=0.0f) { 
  304.                 sb.append(getString(R.string.location_east, 
  305.                         getLocationString(longitude))); 
  306.             } else
  307.                 sb.append(getString(R.string.location_west, 
  308.                         getLocationString(-1.0 * longitude))); 
  309.             } 
  310.             mLocationTextView.setText(sb.toString());// 显示经纬度,其实还可以作反向编译,显示具体地址 
  311.         } 
  312.     } 
  313.  
  314.     // 把经纬度转换成度分秒显示 
  315.     private String getLocationString(double input) { 
  316.         int du = (int) input; 
  317.         int fen = (((int) ((input - du) *3600))) / 60
  318.         int miao = (((int) ((input - du) *3600))) % 60
  319.         return String.valueOf(du) +"°" + String.valueOf(fen) + "′" 
  320.                 + String.valueOf(miao) + "″"
  321.     } 
  322.  
  323.     // 方向传感器变化监听 
  324.     private SensorEventListener mOrientationSensorEventListener =new SensorEventListener() { 
  325.  
  326.         @Override 
  327.         public void onSensorChanged(SensorEvent event) { 
  328.             float direction = event.values[0] * -1.0f; 
  329.             mTargetDirection = normalizeDegree(direction);// 赋值给全局变量,让指南针旋转 
  330.         } 
  331.  
  332.         @Override 
  333.         public void onAccuracyChanged(Sensor sensor,int accuracy) { 
  334.         } 
  335.     }; 
  336.  
  337.     // 调整方向传感器获取的值 
  338.     private float normalizeDegree(float degree) { 
  339.         return (degree +720) % 360
  340.     } 
  341.  
  342.     // 位置信息更新监听 
  343.     LocationListener mLocationListener = new LocationListener() { 
  344.  
  345.         @Override 
  346.         public void onStatusChanged(String provider,int status, Bundle extras) { 
  347.             if (status != LocationProvider.OUT_OF_SERVICE) { 
  348.                 updateLocation(mLocationManager 
  349.                         .getLastKnownLocation(mLocationProvider)); 
  350.             } else
  351.                 mLocationTextView.setText(R.string.cannot_get_location); 
  352.             } 
  353.         } 
  354.  
  355.         @Override 
  356.         public void onProviderEnabled(String provider) { 
  357.         } 
  358.  
  359.         @Override 
  360.         public void onProviderDisabled(String provider) { 
  361.         } 
  362.  
  363.         @Override 
  364.         public void onLocationChanged(Location location) { 
  365.             updateLocation(location);// 更新位置 
  366.         } 
  367.     }; 
原创粉丝点击