Android LocationGPS中的应用()

分类: Android 2011-03-25 10:06 1386人阅读 评论(0) 收藏 举报

新建Android Project,注意选择Google APIs

打开AndroidManifest.xml,在其中加入GPS使用权限:

< uses-permission android:name= "android.permission.ACCESS_COARSE_LOCATION" /> < uses-permission android:name= "android.permission.ACCESS_FINE_LOCATION" />

main.java的代码如下:

public class main extends Activity {

/** Called when the activity is first created. */

private LocationManager locationManager ;

private String provider ;

private Location location ;

private Address address ;

@Override

public void onCreate(Bundle savedInstanceState) {

super .onCreate(savedInstanceState);

setContentView(R.layout. main );

// 获取 LocationManager 服务

locationManager = (LocationManager) this

.getSystemService(Context. LOCATION_SERVICE );

// 获取 Location Provider

getProvider();

// 如果未设置位置源,打开 GPS 设置界面

openGPS();

// 获取位置

location = locationManager .getLastKnownLocation( provider );

// 显示位置信息到文字标签

updateWithNewLocation( location );

// 注册监听器 locationListener ,第 2 3 个参数可以控制接收 gps 消息的频度以节省电力。第 2 个参数为毫秒,

// 表示调用 listener 的周期,第 3 个参数为米 , 表示位置移动指定距离后就调用 listener

locationManager .requestLocationUpdates( provider , 2000, 10,

locationListener );

}

// 判断是否开启 GPS ,若未开启,打开 GPS 设置界面

private void openGPS() {

if ( locationManager .isProviderEnabled(android.location.LocationManager. GPS_PROVIDER )

|| locationManager .isProviderEnabled(android.location.LocationManager. NETWORK_PROVIDER )

) {

Toast.makeText ( this , " 位置源已设置! " , Toast. LENGTH_SHORT ).show();

return ;

}

Toast.makeText ( this , " 位置源未设置! " , Toast. LENGTH_SHORT ).show();

// 转至 GPS 设置界面

Intent intent = new Intent(Settings. ACTION_SECURITY_SETTINGS );

startActivityForResult(intent,0);

}

// 获取 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) {

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" +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 ());

result= gc.getFromLocation(location.getLatitude(), location.getLongitude(), 1);

}

} catch (Exception e) {

e.printStackTrace();

}

return result;

}

}

如果,要想在模拟器中看到效果,还需要在DDMSEmulator Control面板中进行一些设置。如果你看不到Emulator Control面板,可以从window->Show view->Other…中打开它:

Emulator Control面板中,你可以找到一个Location Controls的地方:

你可以在LongitudeLatitude中输入一个虚拟的经纬度,然后点击Send,可以把模拟器的位置修改为指定位置。此时运行程序,即可看到如图所示的信息:

有时候,你可能出现“无法获取地理信息”的错误。这可能是没有开启“启用GPS卫星”选项。不要奇怪,在模拟器中,“使用无线网络”是无效的,使用该选项无法获取地理信息,因为模拟器中根本没有sim卡,也就无法通过基站来定位了。

如果在真机上就不同了。如果机器没有内置GPS模块,那么启用GPS卫星选项反而无法进行定位,具体情况只有多试几次才能明白。

@font-face { font-family: "宋体"; }@font-face { font-family: "Cambria"; }p.MsoNormal, li.MsoNormal, div.MsoNormal { margin: 0cm 0cm 10pt; font-size: 12pt; font-family: "Times New Roman"; }div.Section1 { page: Section1; }

Geocoder需要访问internet,在真机上调试请打开wifi或者3G网络。

Android LocationGPS中的应用()

分类: Android 2011-04-02 14:01 1030人阅读 评论(1) 收藏 举报

这一篇其实跟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

我们这个应用就一个Activitymain.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类,呆会再介绍。

AndroidService有两种使用方式。一种比较简单,使用ActivitystartService/stopService方法启动关闭服务。但这种方式不能满足我们的需要,因为无法向Service类传递参数。因此我们决定使用第2种方式,即IBinder的方式。其实第2种方式跟第1种方式的区别只在于,service实现了onBind方法,在onBind方法中返回了IBinder对象,你可以把更多的代码实现在IBinder中。同时service类会调用IBinder中的方法,于是我们可以通过该方法向IBinder传递参数。

而且在调用方法上,bindServiceunbindService都需要一个 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时,会先调用服务类GpsServiceonBind方法,这个方法会返回一个IBinder对象(其实是IGpsBinder)。在后面GpsService的代码中可以看到,其实onBinder方法返回了一个IGpsBinder的实现类GpsBinder

这样就获得了一个GpsBinder,然后把这个GpsBinder传递给connectiononServiceConnected 方法。通过 onServiceConnected 代码,最终调用的是GpsBinder的接口方法bindService(这个方法中包含了一个参数,我们通过它把main这个Activity传递进去)。

对于服务的解绑定,先调用GpsServiceunOnbind方法。

了解了服务绑定的大致工作过程。接下来就是服务类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,覆盖Service5个生命周期方法。但除了onUnbindonBinder方法外,我们都使用了默认的实现。在onUnbind方法中,我们调用binderunbindService方法进行解绑定。其中,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反射机制调用mContextlocationChanged 方法。如果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();

}

因为在GpsBinderopenGps方法中调用了mContext.showDialog方法。

五、IGpsBinder.java

IGpsBinder中只定义了1个接口方法,这也是在ServiceConnection唯一能识别和调用的IBinder方法:

public interface IGpsBinder {

// 接口暴露方法

public void bindService(Context ctx);

}

方法本身含有一个参数,这个就是把main对象传递给GpsBinder的地方。

六、测试

可以在模拟器中进行测试了,别忘记前面说的利用DDMSLocation Controls来修改Gps坐标。点击“打开GPS监控”菜单,可以看到模拟器从Gps获取到当前位置信息,修改坐标经纬度后点”send”,新坐标立即被捕获并显示在窗口里;点“关闭GPS监控”菜单后,再修改坐标就没用了,还是显示原来的坐标。

更多相关文章

  1. Android(安卓)中文 API (16) —— AnalogClock
  2. linearLayout 和 relativeLayout的属性区别
  3. Android各种资源引用的方法
  4. android 让一个控件按钮居于底部的几种方法
  5. Android(安卓)性能优化的一些方法
  6. 【Android】性能优化的一些方法
  7. android 让一个控件按钮居于底部的几种方法
  8. Android(安卓)限制EditText只能输入数字、限制输入类型、限制输
  9. Android动态加载——加载已安装APK中的类

随机推荐

  1. android,java优秀博客链接汇总分享。。。
  2. android编程开发入门实战例子–hello wor
  3. 常用的 Android(安卓)Studio 快捷键
  4. 在Android中修改快捷方式的图标
  5. android如何查找安装的apk app的包名和Ac
  6. 【WEB服务器】i-jetty环境搭配与编译 .
  7. Android(安卓)Studio 使用说明(一)
  8. Android获取CPU信息(CPU名字和主频)
  9. 设备驱动-----Android关机流程总结
  10. Android(安卓)Window与WMS通信过程