Android实现Service获取当前位置(GPS+基站)的方法

时间:2021-05-19

本文实例讲述了Android实现Service获取当前位置(GPS+基站)的方法。分享给大家供大家参考。具体如下:

需求详情:

1)、Service中每隔1秒执行一次定位操作(GPS+基站)
2)、定位的结果实时显示在界面上(要求得到经度、纬度)

技术支持:

1)、获取经纬度
通过GPS+基站获取经纬度,先通过GPS来获取,如果为空改用基站进行获取–>GPS+基站(基站获取支持联通、电信、移动)。
2)、实时获取经纬度
为了达到实时获取经纬度,需在后台启动获取经纬度的Service,然后把经纬度数据通过广播发送出去,在需要的地方进行广播注册(比如在Activity中注册广播,显示在界面中)–>涉及到Service+BroadcastReceiver+Activity+Thread等知识点。

备注:本文注重实践,如有看不懂的,先去巩固下知识点,可以去看看前面相关的几篇文章。

1、CellInfo实体类–>基站信息

package com.ljq.activity;/** * 基站信息 * * @author jiqinlin * */public class CellInfo { /** 基站id,用来找到基站的位置 */ private int cellId; /** 移动国家码,共3位,中国为460,即imsi前3位 */ private String mobileCountryCode="460"; /** 移动网络码,共2位,在中国,移动的代码为00和02,联通的代码为01,电信的代码为03,即imsi第4~5位 */ private String mobileNetworkCode="0"; /** 地区区域码 */ private int locationAreaCode; /** 信号类型[选 gsm|cdma|wcdma] */ private String radioType=""; public CellInfo() { } public int getCellId() { return cellId; } public void setCellId(int cellId) { this.cellId = cellId; } public String getMobileCountryCode() { return mobileCountryCode; } public void setMobileCountryCode(String mobileCountryCode) { this.mobileCountryCode = mobileCountryCode; } public String getMobileNetworkCode() { return mobileNetworkCode; } public void setMobileNetworkCode(String mobileNetworkCode) { this.mobileNetworkCode = mobileNetworkCode; } public int getLocationAreaCode() { return locationAreaCode; } public void setLocationAreaCode(int locationAreaCode) { this.locationAreaCode = locationAreaCode; } public String getRadioType() { return radioType; } public void setRadioType(String radioType) { this.radioType = radioType; }}

2、Gps类–>Gps封装类,用来获取经纬度

package com.ljq.activity;import android.content.Context;import android.location.Criteria;import android.location.Location;import android.location.LocationListener;import android.location.LocationManager;import android.os.Bundle;public class Gps{ private Location location = null; private LocationManager locationManager = null; private Context context = null; /** * 初始化 * * @param ctx */ public Gps(Context ctx) { context=ctx; locationManager=(LocationManager)context.getSystemService(Context.LOCATION_SERVICE); location = locationManager.getLastKnownLocation(getProvider()); locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 2000, 10, locationListener); } // 获取Location Provider private String 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 return locationManager.getBestProvider(criteria, true); } private LocationListener locationListener = new LocationListener() { // 位置发生改变后调用 public void onLocationChanged(Location l) { if(l!=null){ location=l; } } // provider 被用户关闭后调用 public void onProviderDisabled(String provider) { location=null; } // provider 被用户开启后调用 public void onProviderEnabled(String provider) { Location l = locationManager.getLastKnownLocation(provider); if(l!=null){ location=l; } } // provider 状态变化时调用 public void onStatusChanged(String provider, int status, Bundle extras) { } }; public Location getLocation(){ return location; } public void closeLocation(){ if(locationManager!=null){ if(locationListener!=null){ locationManager.removeUpdates(locationListener); locationListener=null; } locationManager=null; } }}

3、GpsService服务类

package com.ljq.activity;import java.util.ArrayList;import android.app.Service;import android.content.Intent;import android.location.Location;import android.os.IBinder;import android.util.Log;public class GpsService extends Service { ArrayList<CellInfo> cellIds = null; private Gps gps=null; private boolean threadDisable=false; private final static String TAG=GpsService.class.getSimpleName(); @Override public void onCreate() { super.onCreate(); gps=new Gps(GpsService.this); cellIds=UtilTool.init(GpsService.this); new Thread(new Runnable(){ @Override public void run() { while (!threadDisable) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } if(gps!=null){ //当结束服务时gps为空 //获取经纬度 Location location=gps.getLocation(); //如果gps无法获取经纬度,改用基站定位获取 if(location==null){ Log.v(TAG, "gps location null"); //2.根据基站信息获取经纬度 try { location = UtilTool.callGear(GpsService.this, cellIds); } catch (Exception e) { location=null; e.printStackTrace(); } if(location==null){ Log.v(TAG, "cell location null"); } } //发送广播 Intent intent=new Intent(); intent.putExtra("lat", location==null?"":location.getLatitude()+""); intent.putExtra("lon", location==null?"":location.getLongitude()+""); intent.setAction("com.ljq.activity.GpsService"); sendBroadcast(intent); } } } }).start(); } @Override public void onDestroy() { threadDisable=true; if(cellIds!=null&&cellIds.size()>0){ cellIds=null; } if(gps!=null){ gps.closeLocation(); gps=null; } super.onDestroy(); } @Override public IBinder onBind(Intent arg0) { return null; }}

4、GpsActivity–>在界面上实时显示经纬度数据

package com.ljq.activity;import android.app.Activity;import android.content.BroadcastReceiver;import android.content.Context;import android.content.Intent;import android.content.IntentFilter;import android.location.Location;import android.location.LocationManager;import android.os.Bundle;import android.util.Log;import android.widget.EditText;import android.widget.Toast;public class GpsActivity extends Activity { private Double homeLat=26.0673834d; //宿舍纬度 private Double homeLon=119.3119936d; //宿舍经度 private EditText editText = null; private MyReceiver receiver=null; private final static String TAG=GpsActivity.class.getSimpleName(); @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); editText=(EditText)findViewById(R.id.editText); //判断GPS是否可用 Log.i(TAG, UtilTool.isGpsEnabled((LocationManager)getSystemService(Context.LOCATION_SERVICE))+""); if(!UtilTool.isGpsEnabled((LocationManager)getSystemService(Context.LOCATION_SERVICE))){ Toast.makeText(this, "GSP当前已禁用,请在您的系统设置屏幕启动。", Toast.LENGTH_LONG).show(); Intent callGPSSettingIntent = new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS); startActivity(callGPSSettingIntent); return; } //启动服务 startService(new Intent(this, GpsService.class)); //注册广播 receiver=new MyReceiver(); IntentFilter filter=new IntentFilter(); filter.addAction("com.ljq.activity.GpsService"); registerReceiver(receiver, filter); } //获取广播数据 private class MyReceiver extends BroadcastReceiver{ @Override public void onReceive(Context context, Intent intent) { Bundle bundle=intent.getExtras(); String lon=bundle.getString("lon"); String lat=bundle.getString("lat"); if(lon!=null&&!"".equals(lon)&&lat!=null&&!"".equals(lat)){ double distance=getDistance(Double.parseDouble(lat), Double.parseDouble(lon), homeLat, homeLon); editText.setText("目前经纬度\n经度:"+lon+"\n纬度:"+lat+"\n离宿舍距离:"+java.lang.Math.abs(distance)); }else{ editText.setText("目前经纬度\n经度:"+lon+"\n纬度:"+lat); } } } @Override protected void onDestroy() { //注销服务 unregisterReceiver(receiver); //结束服务,如果想让服务一直运行就注销此句 stopService(new Intent(this, GpsService.class)); super.onDestroy(); } /** * 把经纬度换算成距离 * * @param lat1 开始纬度 * @param lon1 开始经度 * @param lat2 结束纬度 * @param lon2 结束经度 * @return */ private double getDistance(double lat1, double lon1, double lat2, double lon2) { float[] results = new float[1]; Location.distanceBetween(lat1, lon1, lat2, lon2, results); return results[0]; } }

5、UtilTool–>工具类

package com.ljq.activity;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.io.UnsupportedEncodingException;import java.net.HttpURLConnection;import java.net.MalformedURLException;import java.net.ProtocolException;import java.net.URL;import java.util.ArrayList;import java.util.Calendar;import java.util.List;import java.util.Locale;import org.apache.http.client.ClientProtocolException;import org.json.JSONException;import org.json.JSONObject;import android.content.Context;import android.location.Location;import android.location.LocationManager;import android.telephony.NeighboringCellInfo;import android.telephony.TelephonyManager;import android.telephony.cdma.CdmaCellLocation;import android.telephony.gsm.GsmCellLocation;import android.util.Log;import android.widget.Toast;public class UtilTool { public static boolean isGpsEnabled(LocationManager locationManager) { boolean isOpenGPS = locationManager.isProviderEnabled(android.location.LocationManager.GPS_PROVIDER); boolean isOpenNetwork = locationManager.isProviderEnabled(android.location.LocationManager.NETWORK_PROVIDER); if (isOpenGPS || isOpenNetwork) { return true; } return false; } /** * 根据基站信息获取经纬度 * * 原理向http://.ljq.activity" android:versionCode="1" android:versionName="1.0"> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".GpsActivity" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <service android:label="GPS服务" android:name=".GpsService" /> </application> <uses-sdk android:minSdkVersion="7" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /></manifest>

效果如下:

希望本文所述对大家的Android程序设计有所帮助。

声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。

相关文章