项目需求讨论 - 定位功能小结

发表于:2019-3-21 10:39

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:青蛙要fly    来源:掘金

  前言:
  我们知道我们的APP有可能需要获取一些地理位置信息。比如定位用户当前的位置,自动选定城市或者区域等。所以这次做个关于定位的一些总结。
  正文
  我们按照二大块来进行分析:一块是相关权限,一块是具体获取地理信息的相关代码。(而实际开发代码中,代码这二块是写在一起的,单纯是为了文章分析从而分开。)
  1.相关权限
  这里的权限我特指了二块:
  一个是本身我们平常开发的app需要获取各种权限,比如相机等,这时候我们既然要获取当前手机的地理信息,肯定也要有一个Location相关的权限。
  本身手机需要打开相应的定位功能,不然app有权限获取,但是手机关闭了整个的定位功能,就还是获取不到。
  1.1 app获取手机权限
  emmm......这块我觉得应该不需要花更多的时间来说明了吧,主要就是:
  检查权限 (checkSelfPermission)
  请求权限(requestPermissions)
  回调事件处理(onRequestPermissionsResult)而我们要申请的权限无非就是Location相关的权限。
   android.permission.ACCESS_COARSE_LOCATION
  允许一个程序访问CellID或WiFi热点来获取粗略的位置
  android.permission.ACCESS_FINE_LOCATION
  允许一个程序访问精良位置(如GPS)
   我们可以看到第一个权限中的英文单词COARSE是粗略的意思,所以在想要粗略的获取一个地理位置的时候,比如我们通过网络来获取,我们只需要申请这个权限即可;第二个权限中的英文单词FINE说明是精确度高的,比如我们需要通过GPS来获取权限的时候,我们就需要申请这个权限。
  一般来说我们的app这二个权限都会申请,因为会需要GPS配合网络一起来确定地理位置信息。
  1.2 手机的定位开关
  在确定我们的app本身已经具有了定位权限后,我们需要知道本身的手机是否已经打开了定位功能。
   public static boolean isLocServiceEnable(Context context) {
  LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
  boolean gps = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
  boolean network = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
  if (gps || network) {
  return true;
  }
  return false;
  }
  我们可以看到上面我们提过一般来获取定位是靠GPS和NetWork二种(为啥是一般呢,因为还有一种 PASSIVE,后面会讲到)。所以我们需要判定这二个功能是否可用。(如果用户把定位功能给关了,那肯定二个都返回false。)
  那这时候假如我们发现用户把定位功能关了。我们肯定需要提示用户,然后协助用户跳到该设置界面,从而让用户把定位功能打开 (毕竟一般的普通用户,可能还真的让他去设置界面找,一时半会还真找不到,毕竟安卓机型太多,每个地方都不同 )。
  比如我们弹出一个弹框,提示用户,按确定按钮的时候跳转到设置的定位界面:
   AlertDialog.Builder builder  = new AlertDialog.Builder(activity);
  builder.setMessage("尚未开启位置定位服务");
  builder.setPositiveButton("开启", new DialogInterface.OnClickListener() {
  @Override
  public void onClick(DialogInterface dialog, int which) {
  //启动定位Activity
  Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
  //比如我们这里设定requestCode为 1
  activity.startActivityForResult(intent , 1);
  }
  });
  builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
  @Override
  public void onClick(DialogInterface dialog, int which) {
  }
  });
  我们可以看到通过隐式启动Action为Settings.ACTION_LOCATION_SOURCE_SETTINGS即可,但是这里记得用使用startActivityForResult而不是startActivity,我看很多网上的的写法是用startActivity,单纯跳转过去是没问题,但是我们需要知道返回的结果,万一用户跳转过去后没有打开呢。
  既然我们用了statActivityForResult来启动,当我们返回回到自己的app界面的时候,在onActivityForResult中需要来判断,本来因为习惯性思维,所以以为自动在onActivityForResult的返回参数resultCode可以用来判断,后来发现不管开启不开启,都是返回RESULT_CANCELED,也就是0,毕竟在那个设置界面我们并没有设定setResult(xxx);所以当判断了requestCode之后,我们需要重新判断一次定位是否可用了。
   @Override
  protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  super.onActivityResult(requestCode, resultCode, data);
  if (requestCode == 1) {
  //我们通过上面提过的方法,再次去判断是否gps和network的provider都无效。
  if (!isLocServiceEnable(MainActivity.this)) {
  Toast.makeText(this, "未开启定位功能,请手动选择地址位置", Toast.LENGTH_LONG).show();
  } else {
  //去获取具体的地理位置信息...
  }
  }
  }
  2 获取地理位置
  我们上面提到了我们想要获取地理位置的时候,需要具备上面的基本权限,然后才能正常使用我们的相关api去获取信息。
  主要是通过```LocationManager``这个类。
  但是android.location包下的并不是谷歌推荐的:
  翻译过来就是:此API不是访问Android位置的推荐方法。
 
     上文内容不用于商业目的,如涉及知识产权问题,请权利人联系博为峰小编(021-64471599-8017),我们将立即处理。
21/212>
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号