基于位置的服务包括三个方面:获取位置、地图服务、地理编码服务。

获取位置是所有基于位置的服务的基础,Android获取位置使用LocationManager类。首先获取LocationManager的实例,然后一般要检查位置服务是否开启。如果未开启,就打开设置位置服务界面。如果已开启,再检查应用的定位权限是否允许。都通过了,就可以设置一个位置监听器,有了位置信息就会调用监听器的相应方法。设置监听器时可以设置位置监听的最小时间间隔和最小距离间隔,只有这两个条件都满足时才会有位置信息。流程和关键代码如下图:

下面是一个获取位置的例子。例子的界面如下,最上面一行是两项设置,记录位置的最小时间间隔和最小距离,只有这两个条件同时满足,才会产生一个位置数据。第二行是两个按钮,分别启动和停止位置监听。再下面是一个文本,显示监听到的位置信息。

例子中,首先要在onCreate中获取LocationManager实例,并检查设备是否开启了位置服务,代码如下:
manager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
if(!manager.isProviderEnabled(LocationManager.GPS_PROVIDER) &&
!manager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
askLocationSettings();
}
可以从手机最上面的功能栏中开启/关闭手机的位置服务,如下图:

如果位置服务未开启,可以询问用户是否转到位置服务设置界面。位置服务设置界面通过Intent来启动,动作是android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS。代码如下:
void askLocationSettings(){
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("开启位置服务");
builder.setMessage("本应用需要开启位置服务,是否去设置界面开启位置服务?");
builder.setPositiveButton("是", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface arg0, int arg1) {
Intent intent = new Intent(
android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
MainActivity.this.startActivity(intent);
}
});
builder.setNegativeButton("否", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface arg0, int arg1) {
Toast.makeText(MainActivity.this, "No location provider to use",
Toast.LENGTH_SHORT).show();
}
});
builder.show();
}
位置服务设置界面如下:

如果设备开启了位置服务,就可以创建一个位置信息监听器,在监听时需要传给LocationManager。在事件监听方法中将经度、纬度、高度、速度等位置信息输出。代码如下:
listener = new LocationListener(){
public void onLocationChanged(Location arg0) {
String txt = "Longitude:" + arg0.getLongitude()
+ ", Latitude:" + arg0.getLatitude()
+ ", Altitude" + arg0.getAltitude()
+ ", Speed:" + arg0.getSpeed();
// 经度,纬度,高度,速度
tvResult.append(txt + "\n");
}
public void onProviderDisabled(String arg0) {}
public void onProviderEnabled(String arg0) {}
public void onStatusChanged(String arg0, int arg1, Bundle arg2) {}
};
启动位置监听需要调用LocationManager的requestLocationUpdates()方法,方法的第一个参数是位置服务提供者。一个设备上可能有多个位置服务提供者,比如gps,wifi,北斗等,所以要先根据定位需求寻找一个最匹配的提供者,使用的方法是LocationManager的getBestProvider()方法。另外,获取当前位置需要一定的时间,而有些应用又已启动就需要一个定位信息,此时可以使用上次使用时的最后已知位置。该位置保存在缓存中,可以通过LocationManager的getLastKnownLocation()方法获得。具体代码如下:
void startListening(){
Criteria crt = new Criteria(); // 位置监听标准
crt.setHorizontalAccuracy(Criteria.ACCURACY_HIGH); // 水平精度高
crt.setAltitudeRequired(true); // 需要高度
String provider = manager.getBestProvider(crt, true); // 寻找最匹配的provider
Location l = manager.getLastKnownLocation(provider); // 取最后已知位置,即缓存中的位置
if(l!=null) tvResult.append(provider + "-LastKnown:" + l.toString() + "\n");
long period = Long.parseLong(etPeriod.getText().toString()); // 最小时间间隔
int distance = Integer.parseInt(etDistance.getText().toString()); // 最小距离
manager.requestLocationUpdates(provider, period*1000, distance, listener); // 开始监听
tvResult.append(provider + "-Location listener started.\n");
}
Android6.0以上系统需要应用运行时进行动态权限申请,所以在开始监听位置前需要检查权限,如果没有许可就进行询问。主要代码是:
if (ActivityCompat.checkSelfPermission(activity, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 101);
return;
}
停止位置监听使用LocationManager的removeUpdates()方法,代码如下:
manager.removeUpdates(listener);
tvResult.append("Location listener stoped.\n");
监听位置需要在配置文件里声明权限:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
例子中用到的相关类包括:
1)android.location.LocationManager类,方法有:
2)android.location.Criteria类,方法有:
3)android.location.Location类,方法有:
4)android.location.LocationListener接口,方法有:
我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当
我已经在Sinatra上创建了应用程序,它代表了一个简单的API。我想在生产和开发上进行部署。我想在部署时选择,是开发还是生产,一些方法的逻辑应该改变,这取决于部署类型。是否有任何想法,如何完成以及解决此问题的一些示例。例子:我有代码get'/api/test'doreturn"Itisdev"end但是在部署到生产环境之后我想在运行/api/test之后看到ItisPROD如何实现? 最佳答案 根据SinatraDocumentation:EnvironmentscanbesetthroughtheRACK_ENVenvironm
有没有办法在这个简单的get方法中添加超时选项?我正在使用法拉第3.3。Faraday.get(url)四处寻找,我只能先发起连接后应用超时选项,然后应用超时选项。或者有什么简单的方法?这就是我现在正在做的:conn=Faraday.newresponse=conn.getdo|req|req.urlurlreq.options.timeout=2#2secondsend 最佳答案 试试这个:conn=Faraday.newdo|conn|conn.options.timeout=20endresponse=conn.get(url
我有一个存储主机名的Ruby数组server_names。如果我打印出来,它看起来像这样:["hostname.abc.com","hostname2.abc.com","hostname3.abc.com"]相当标准。我想要做的是获取这些服务器的IP(可能将它们存储在另一个变量中)。看起来IPSocket类可以做到这一点,但我不确定如何使用IPSocket类遍历它。如果它只是尝试像这样打印出IP:server_names.eachdo|name|IPSocket::getaddress(name)pnameend它提示我没有提供服务器名称。这是语法问题还是我没有正确使用类?输出:ge
我想获取模块中定义的所有常量的值:moduleLettersA='apple'.freezeB='boy'.freezeendconstants给了我常量的名字:Letters.constants(false)#=>[:A,:B]如何获取它们的值的数组,即["apple","boy"]? 最佳答案 为了做到这一点,请使用mapLetters.constants(false).map&Letters.method(:const_get)这将返回["a","b"]第二种方式:Letters.constants(false).map{|c
我们的git存储库中目前有一个Gemfile。但是,有一个gem我只在我的环境中本地使用(我的团队不使用它)。为了使用它,我必须将它添加到我们的Gemfile中,但每次我checkout到我们的master/dev主分支时,由于与跟踪的gemfile冲突,我必须删除它。我想要的是类似Gemfile.local的东西,它将继承从Gemfile导入的gems,但也允许在那里导入新的gems以供使用只有我的机器。此文件将在.gitignore中被忽略。这可能吗? 最佳答案 设置BUNDLE_GEMFILE环境变量:BUNDLE_GEMFI
我安装了ruby版本管理器,并将RVM安装的ruby实现设置为默认值,这样'哪个ruby'显示'~/.rvm/ruby-1.8.6-p383/bin/ruby'但是当我在emacs中打开inf-ruby缓冲区时,它使用安装在/usr/bin中的ruby。有没有办法让emacs像shell一样尊重ruby的路径?谢谢! 最佳答案 我创建了一个emacs扩展来将rvm集成到emacs中。如果您有兴趣,可以在这里获取:http://github.com/senny/rvm.el
这似乎非常适得其反,因为太多的gem会在window上破裂。我一直在处理很多mysql和ruby-mysqlgem问题(gem本身发生段错误,一个名为UnixSocket的类显然在Windows机器上不能正常工作,等等)。我只是在浪费时间吗?我应该转向不同的脚本语言吗? 最佳答案 我在Windows上使用Ruby的经验很少,但是当我开始使用Ruby时,我是在Windows上,我的总体印象是它不是Windows原生系统。因此,在主要使用Windows多年之后,开始使用Ruby促使我切换回原来的系统Unix,这次是Linux。Rub
我正在玩HTML5视频并且在ERB中有以下片段:mp4视频从在我的开发环境中运行的服务器很好地流式传输到chrome。然而firefox显示带有海报图像的视频播放器,但带有一个大X。问题似乎是mongrel不确定ogv扩展的mime类型,并且只返回text/plain,如curl所示:$curl-Ihttp://0.0.0.0:3000/pr6.ogvHTTP/1.1200OKConnection:closeDate:Mon,19Apr201012:33:50GMTLast-Modified:Sun,18Apr201012:46:07GMTContent-Type:text/plain
假设我有这个范围:("aaaaa".."zzzzz")如何在不事先/每次生成整个项目的情况下从范围中获取第N个项目? 最佳答案 一种快速简便的方法:("aaaaa".."zzzzz").first(42).last#==>"aaabp"如果出于某种原因你不得不一遍又一遍地这样做,或者如果你需要避免为前N个元素构建中间数组,你可以这样写:moduleEnumerabledefskip(n)returnto_enum:skip,nunlessblock_given?each_with_indexdo|item,index|yieldit