这一篇其实跟GPS毫无关系。 继续上一篇的内容,讲GPS以外的东西,比如说Service的使用。比如说gps监控,它并不需要任何UI,在后台默默地运行就行。为什么不做成Service呢?悄悄地向服务器发送用户的位置坐标是一个不错的想法,因为它完全不需要用户的干预。当然为了保留用户权利,我们应当留一个地方让用户把服务关掉。
继续前一篇的工程,如果你没有保留前面的工作也没有关系,从头来就是了。
一、AndroidManifext.xml
新建Google Project ,注意选择Google APIs。
编辑AndroidManifest.xml,加入相应的权限:
<
uses-permission
android:name
=
"android.permission.ACCESS_COARSE_LOCATION"
/>
<
uses-permission
android:name
=
"android.permission.ACCESS_FINE_LOCATION"
/>
其次,由于我们使用了服务,需要在<application></application>标签加入一个<service>标签,以注册自己的服务:
<
service
android:label
=
"@string/app_name"
android:name
=
".GpsService"
>
<
intent-filter
>
<
action
android:name
=
"start_gps_service"
></
action
>
<
category
android:name
=
"android.intent.category.DEFAULT"
></
category
>
</
intent-filter
>
</
service
>
这个.GpsService是我们自定义的service类,它可以相应一个”start_aps_servicee”的Action。
二、main.java
我们这个应用就一个Activity。main.xml不用做任何修改。打开main.java,以下代码在菜单中添加了2个菜单项,以便让用户开启和关闭gps:
//
创建菜单
public
boolean
onCreateOptionsMenu(Menu menu) {
//
TODO
Auto-generated
method stub
super
.onCreateOptionsMenu(menu);
menu.add(0, Menu.
FIRST
+ 1, 1,
"
打开
GPS
监控
"
);
menu.add(0, Menu.
FIRST
+ 2, 2,
"
关闭
GPS
监控
"
);
return
true
;
}
//
菜单项监听
public
boolean
onOptionsItemSelected(MenuItem item) {
Intent i;
//
TODO
Auto-generated
method stub
super
.onOptionsItemSelected(item);
switch
(item.getItemId()) {
case
Menu.
FIRST
+ 1:
//
打开
GPS
监控
this
.setTitle(
"GPS Service Started"
);
i =
new
Intent(
this
, GpsService.
class
);
this
.bindService(i,
connection
, Context.
BIND_AUTO_CREATE
);
break
;
case
Menu.
FIRST
+ 2:
//
关闭
GPS
监控
this
.setTitle(
"GPS Service Stopped"
);
//
通过检测
mBinder
是否为空来判断服务是否已绑定,从而避免
service not registered
错误
if
(
mBinder
!=
null
){
i =
new
Intent(
this
, GpsService.
class
);
this
.unbindService(
connection
);
mBinder=null;//释放mBinder,防止重复解绑定
}
break
;
}
return
true
;
}
this.bindService
和this.
unbindService
和分别启动和关闭服务。这里的服务是GpsService类,呆会再介绍。
Android的Service有两种使用方式。一种比较简单,使用Activity的startService/stopService方法启动关闭服务。但这种方式不能满足我们的需要,因为无法向Service类传递参数。因此我们决定使用第2种方式,即IBinder的方式。其实第2种方式跟第1种方式的区别只在于,service实现了onBind方法,在onBind方法中返回了IBinder对象,你可以把更多的代码实现在IBinder中。同时service类会调用IBinder中的方法,于是我们可以通过该方法向IBinder传递参数。
而且在调用方法上,bindService和unbindService都需要一个
ServiceConnection
类的参数。因此我们在main.java中申明了这个
ServiceConnection:
ServiceConnection
connection
=
new
ServiceConnection() {
@Override
public
void
onServiceConnected(ComponentName arg0, IBinder arg1) {
//
TODO
Auto-generated method stub
mBinder
= (IGpsBinder)
arg1;
if
(
mBinder
!=
null
) {
mBinder
.bindService(main.
this
);
}
}
@Override
public
void
onServiceDisconnected(ComponentName name) {
//
TODO
Auto-generated method stub
}
};
在这个 ServiceConnection 示例中,有两个方法需要实现。我们关注的只有
onServiceConnected方法。
这个方法在连接服务后调用。我们在这个方法中使用了一个接口对象IGpsBinder:
IGpsBinder
mBinder
=
null
;
IGpsBinder是一个接口,它对应的实现是GpsBinder类。这两个东西后面会说。
先看服务的绑定,代码:
i =
new
Intent(
this
, GpsService.
class
);
this
.bindService(i,
connection
, Context.
BIND_AUTO_CREATE
);
首先,Intent中已经包含了服务的实现类GpsService,这样在bindService时就可以把服务类传递进去。其次,ServiceConnection也被传递进去了。
这样,当bindService时,会先调用服务类GpsService的onBind方法,这个方法会返回一个IBinder对象(其实是IGpsBinder)。在后面GpsService的代码中可以看到,其实onBinder方法返回了一个IGpsBinder的实现类GpsBinder。
这样就获得了一个GpsBinder,然后把这个GpsBinder传递给connection的
onServiceConnected
方法。通过
onServiceConnected
代码,最终调用的是GpsBinder的接口方法bindService(这个方法中包含了一个参数,我们通过它把main这个Activity传递进去)。
对于服务的解绑定,先调用GpsService的unOnbind方法。
了解了服务绑定的大致工作过程。接下来就是服务类GpsService了。
三、GpsService.java
public
class
GpsService
extends
Service {
private
GpsBinder
binder
=
new
GpsBinder();
@Override
public
void
onCreate() {
super
.onCreate();
}
@Override
public
void
onDestroy() {
//
TODO
Auto-generated
method stub
super
.onDestroy();
}
@Override
public
void
onStart(Intent
intent,
int
startId) {
//
TODO
Auto-generated
method stub
super
.onStart(intent, startId);
}
@Override
public
boolean
onUnbind(Intent
intent) {
//
TODO
Auto-generated
method stub
binder
.unbindService();
return
true
;
}
@Override
public
IBinder
onBind(Intent intent) {
//
TODO
Auto-generated
method stub
return
binder
;
}
}
可以看到,GpsService的代码很简单,继承了Service,覆盖Service的5个生命周期方法。但除了onUnbind和onBinder方法外,我们都使用了默认的实现。在onUnbind方法中,我们调用binder的unbindService方法进行解绑定。其中,binder是一个GpsBinder,后面会介绍。在onBind方法中,我们返回了GpsBinder对象。这个GpsBinder对象能为我们做些什么呢?
四、GpsBinder.java
public
class
GpsBinder
extends
Binder
implements
IGpsBinder{
private
LocationManager
locationManager
;
private
Location
location
;
private
String
provider
;
private
Context
mContext
=
null
;
public
GpsBinder(){
}
@Override
//
接口暴露方法
public
void
bindService(Context ctx){
mContext
=ctx;
//
获取
LocationManager
服务
locationManager
= (LocationManager)
mContext
.getSystemService(Context.
LOCATION_SERVICE
);
//
如果未设置位置源,打开
GPS
设置界面
openGPS();
//
获取
Location Provider
getProvider();
//
获取位置
location
=
locationManager
.getLastKnownLocation(
provider
);
//
显示位置信息到文字标签
updateWithNewLocation(
location
);
//
注册监听器
locationListener
,第
2
、
3
个参数可以控制接收
gps
消息的频度以节省电力。第
2
个参数为毫秒,
//
表示调用
listener
的周期,第
3
个参数为米
,
表示位置移动指定距离后就调用
listener
locationManager
.requestLocationUpdates(
provider
, 2000, 10,
locationListener
);
}
public
void
unbindService(){
//
注销
location
监听器
locationManager
.removeUpdates(
locationListener
);
}
//
获取
Location Provider
private
void
getProvider() {
//
构建位置查询条件
Criteria criteria =
new
Criteria();
//
查询精度:高
criteria.setAccuracy(Criteria.
ACCURACY_FINE
);
//
是否查询海拨:否
criteria.setAltitudeRequired(
false
);
//
是否查询方位角
:
否
criteria.setBearingRequired(
false
);
//
是否允许付费:是
criteria.setCostAllowed(
true
);
//
电量要求:低
criteria.setPowerRequirement(Criteria.
POWER_LOW
);
//
返回最合适的符合条件的
provider
,第
2
个参数为
true
说明
,
如果只有一个
provider
是有效的
,
则返回当前
provider
provider
=
locationManager
.getBestProvider(criteria,
true
);
}
// Gps
消息监听器
private
final
LocationListener
locationListener
=
new
LocationListener()
{
//
位置发生改变后调用
public
void
onLocationChanged(Location location) {
updateWithNewLocation(location);
}
// provider
被用户关闭后调用
public
void
onProviderDisabled(String provider) {
updateWithNewLocation(
null
);
}
// provider
被用户开启后调用
public
void
onProviderEnabled(String provider) {
}
// provider
状态变化时调用
public
void
onStatusChanged(String provider,
int
status, Bundle
extras) {
}
};
// Gps
监听器调用,处理位置信息
private
void
updateWithNewLocation(Location location) {
//
利用反射机制调用
mContext
的
locationChanged
方法
Class<?>[] types =
new
Class[] {Location.
class
};
//
这个方法有
1
个参数
try
{
Method m =
mContext
.getClass().getMethod(
"locationChanged"
, types);
if
(m !=
null
)
m.invoke(
mContext
, location);
}
catch
(Exception e) {
Log.e
(GpsBinder.
class
.getName(),
e.toString());
}
Log.i
(GpsBinder.
class
.getName(),
"location is
changed:"
+location);
}
//
判断是否开启
GPS
,若未开启,打开
GPS
设置界面
private
void
openGPS() {
boolean
bGPS =
locationManager
.isProviderEnabled(android.location.LocationManager.
GPS_PROVIDER
);
boolean
bNetwork =
locationManager
.isProviderEnabled(android.location.LocationManager.
NETWORK_PROVIDER
);
Log.e
(
":::"
,
"bGPS="
+ bGPS +
"bNetwork="
+ bNetwork);
if
(bGPS || bNetwork) {
Toast.makeText
(
mContext
,
"
位置源已设置!
"
, Toast.
LENGTH_SHORT
).show();
return
;
}
// Toast.makeText(this, "
位置源未设置!
", Toast.LENGTH_SHORT).show();
((Activity)
mContext
).showDialog(0);
}
}
这个代码不解释了,完全就是把我们在上一篇中关于Location的代码搬到这里了。需要注意的是
unbindService
、
bindService
、
updateWithNewLocation
方法。
unbindService方法前面已提过,调用main对象的unbindService方法时被调用,它会把location监听器注销,于是位置变化不再通知监听器。
bindService方法是IGpsBinder中的接口方法,它注册了location监听器,当Gps芯片检测到位置发生改变时通知locationListener监听器。值得注意的是这个方法中的ctx参数,实际上是把main这个Activity传递进来了,并且保存在mContext变量中,这样在
updateWithNewLocation
方法中可以使用main。
updateWithNewLocation
方法是监听器里的主要方法,它使用了一个技巧:利用java反射机制调用mContext的
locationChanged
方法。如果main没有实现
locationChanged
方法,则什么也不会做。这个技巧用来更新UI是很实用的。
当然,我们在main.java中也实现了这个
locationChanged
方法:
public
void
locationChanged(Location loc) {
updateWithNewLocation(loc);
}
// Gps
监听器调用,处理位置信息
private
void
updateWithNewLocation(Location location) {
String latLongString;
TextView myLocationText = (TextView) findViewById(R.id.
text
);
if
(location !=
null
) {
double
lat =
location.getLatitude();
double
lng =
location.getLongitude();
latLongString =
"
纬度
:"
+ lat +
"/n
经度
:"
+ lng;
}
else
{
latLongString =
"
无法获取地理信息
"
;
}
myLocationText.setText(
"
您当前的位置是
:/n"
+ latLongString +
"/n
地址
:"
+ getAddressString(getAddressbyGeoPoint(location)));
}
//
获取地址信息
private
List<Address> getAddressbyGeoPoint(Location location) {
List<Address> result =
null
;
//
先将
Location
转换为
GeoPoint
// GeoPoint gp
=getGeoByLocation(location);
try
{
if
(location !=
null
) {
//
获取
Geocoder
,通过
Geocoder
就可以拿到地址信息
Geocoder gc =
new
Geocoder(
this
, Locale.getDefault
());
// double geoLatitude = (int
)
gp.getLatitudeE6() / 1E6;
// double geoLongitude = (int
)
gp.getLongitudeE6() / 1E6;
result = gc.getFromLocation(location.getLatitude(),
location.getLongitude(), 1);
}
}
catch
(Exception e) {
e.printStackTrace();
}
return
result;
}
//
把地址信息转换为一定格式的字符串
private
String
getAddressString(List<Address> list) {
if
(list !=
null
&& list.size() > 0) {
Address add = list.get(0);
return
String.format
(
"%s%s%s%s"
, add.getCountryName(),
add.getAdminArea(),
add.getLocality(),
add.getThoroughfare());
}
else
return
""
;
}
内容很多,但大部分仍然是上一篇中实现过的内容。
此外,在main.java中还要实现托管对话框:
protected
Dialog
onCreateDialog(
int
id) {
Log.e
(
"::::"
,
"ddsdg"
);
return
new
AlertDialog.Builder(
this
)
.setMessage(
"
位置源未设置!是否现住设置位置源?
"
)
.setPositiveButton(
"
是
"
,
new
DialogInterface.OnClickListener() {
public
void
onClick(DialogInterface dialog,
int
which) {
//
转至
GPS
设置界面
Intent intent =
new
Intent(
Settings.
ACTION_SECURITY_SETTINGS
);
startActivityForResult(intent, 0);
}
})
.setNegativeButton(
"
不
"
,
new
DialogInterface.OnClickListener() {
public
void
onClick(DialogInterface dialog,
int
which) {
dialog.dismiss();
//
removeDialog(0);
移除对话框
}
}).create();
}
因为在GpsBinder的openGps方法中调用了mContext.showDialog方法。
五、IGpsBinder.java
IGpsBinder中只定义了1个接口方法,这也是在ServiceConnection唯一能识别和调用的IBinder方法:
public
interface
IGpsBinder
{
//
接口暴露方法
public
void
bindService(Context ctx);
}
方法本身含有一个参数,这个就是把main对象传递给GpsBinder的地方。
六、测试
可以在模拟器中进行测试了,别忘记前面说的利用DDMS的Location Controls来修改Gps坐标。点击“打开GPS监控”菜单,可以看到模拟器从Gps获取到当前位置信息,修改坐标经纬度后点”send”,新坐标立即被捕获并显示在窗口里;点“关闭GPS监控”菜单后,再修改坐标就没用了,还是显示原来的坐标。
分享到:
相关推荐
比如说gps监控,它并不需要任何UI,在后台默默地运行就行。为什么不做成Service呢?悄悄地向服务器发送用户的位置坐标是一个不错的想法,因为它完全不需要用户的干预。当然为了保留用户权利,我们应当留一个地方让...
一,在很多提供定位服务的应用程序中,不仅需要获取当前的位置信息,还需要监视位置的变化,在位置改变时调用特定的处理方法 ,其中LocationManager提供了一种便捷、高效的位置监视方法requestLocationUpdates(),...
在Android应用中实现GPS返回Location经纬度值 不为null 可以实现
GPS的应用开发,里面都是详细的代码还有注释 有一下内容: 支持GPS的核心API 获取LocationProvider 获取可用的LocationProvider 通过名称获取指定LocationProvider 根据Criteria获得LocationProvider
Android中的GPS应用,讲述了LocationManager、LocationProvider、跟踪、定位、Geocoder正逆向编解码和可视化位置服务 第三篇 应用篇 第15章 Android应用案例——移动警务通 Android 应用案例——移动警务通,通过...
Android应用源码之androidGPS及WIFI基站定位坐标源码.zip
安卓GPS应用案例,LocationManager和locationProvider,Criteria
Android中应用此代码实现返回location经纬度,已验证可以实现
第11章 Android的GPS应用开发 11.1 GPS在手机中的应用 11.2 Android Location-Based API简介 11.3 Android模拟器支持的GPS定位文件 11.3.1 KML 11.3.2 NMEA 11.4 应用实例详解:确定当前 位置的GPS程序 11.4.1 实例...
由于Android构建在开源代码的框架之上,而且提供了强大的SDK库和开放的理念,所以它为广大的没有任何移动应用程序开发经验的新手开辟了一条开发完美的移动应用程序的康庄大道。而富有经验的移动开发人员现在也可以...
包含内容: ...第六章:GPS应用开发 41 一、 支持GPS的核心API 41 二、 获取LocationProvider 42 三、 获取定位信息 43 第七章:整合地图服务 46 一、 整合高德Map服务 46 二、 整合百度Map服务 52
MockLocation 是一个项目,是一个 Android 应用程序,可用于设置 GPS 提供商返回的虚假 GPS 位置以进行测试,让您记录路线并回放。 它使用 ActionBarSherlock、Google Maps Android API v2 和我编写的位置库。 ...
GPS是Android系统中重要的组成部分,通过它可以衍生出众多的与位置相关的应用。 Android的GPS有一个专门的管理类,称为LocationManager,所有的GPS定位服务都由其对象产生并进行控制。 首先需要明确的是,...
的 Android SDK 提供了在 Android 平台上使用 JaVa 语言进行 Android 应用开发必须的工具和 API 接口。 特性 • 应用程序框架 支持组件的重用与替换 • Dalvik Dalvik Dalvik Dalvik 虚拟机 专为移动设备优化 • ...
Android进阶高级:蓝牙/WIFI SMS/MMS 应用实现 深层次解析GPS原理,实现LocationManager/LocationProvider 进行定位/跟踪/查找/趋近警告以及Geocoder正逆向编解码等技术细节 2D图形库(Graphics/View)详解 SDCARD/...
AMap_Android_API_Demo_V2.0.4(Location_API_V1.0.2).zip Android 4.0下指南针开发源码,可在Nexus 4上完美运行.zip Android GPS 开发client端代码分享.zip android 获取精度纬度.rar androidGPS及WIFI基站定位坐标...
今天因为工作需要,把以前编写的一个GPS测试程序拿出来重新修改了一下。...NMEA是一种标准化数据格式,不仅仅GPS上应用了,其他一些工业通信也是使用这种标准化数据格式。解析相关数据然后显示出来,就完
9.2.1 在应用程序中使用SMS 9.2.2 发送SMS信息 9.2.3 监听SMS消息 9.2.4 紧急响应的SMS示例 9.2.5 紧急响应自动化 9.3 小结 第10章 访问Android硬件 10.1 使用媒体API 10.1.1 播放媒体资源 10.1.2 录制多媒体 10.2 ...
该应用程序基于Aaron Parecki开发的iOS版Overland应用程序 这是一项从Android设备收集数据以测试Android的Core Location API及其各种设置的实验。 该应用程序跟踪: GPS定位运动状态(步行,跑步,驾驶,骑自行车,...