Android(安卓)获取经纬度的服务
16lz
2021-01-25
Android 获取经纬度的服务
使用原生Android API 编写一个Service类获取经纬度信息(本文仅作为学习笔记来使用,若侵犯到您的权益,请及时与我联系,我会删除涉及侵犯到您的内容)。
一, 实现步骤
- 添加对应的权限
- 编写Service类实现获取经纬度的功能
- 将获取的经纬度使用广播传递到MainAtivity做数据的展示
- 踩过的坑
二,代码实现
1).在AndroidManifest.xml添加权限
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.INTERNET" />
2).编写Service类
Service继承IntentService类,并实现了LocationListener接口,具体代码如下
public class LocationListenerService extends IntentService implements LocationListener { public static final String TAG = "LocationListenerService"; public static final String SERVICE_NAME = "LocationListenerService"; private LocationManager locationManager; private int count=0; /** * Creates an IntentService. Invoked by your subclass's constructor. * */ public LocationListenerService() { super(SERVICE_NAME); } @Override protected void onHandleIntent(@Nullable Intent intent) { locationManager = (LocationManager) getSystemService(LOCATION_SERVICE); // 检查定位服务是否打开 if (locationManager.getProvider(LocationManager.NETWORK_PROVIDER) != null || locationManager.getProvider(LocationManager.GPS_PROVIDER) != null) { Log.i(TAG, "正在定位"); // Permission check if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { return; } //设置数据更新的条件,参数分别为1,使用GPS 2,最小时间间隔 3000毫秒 3,最短距离 100 4,设置事件监听者 this(类继承了Locationlistener) locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 3000, 100, this); } else { Log.i(TAG, "无法定位"); Toast.makeText(this, "无法定位,请打开定位服务", Toast.LENGTH_SHORT).show(); Intent i = new Intent(); i.setAction(Settings.ACTION_LOCATION_SOURCE_SETTINGS); startActivity(i); } } @Override public void onLocationChanged(Location location) { Log.i(TAG, "LocationChanged"); double latitude = location.getLatitude(); Log.i(TAG, "纬度 =" + latitude); double longitude = location.getLongitude(); Log.i(TAG, "经度 =" + longitude); //将location作为参数传递给广播 BCL(location); } /** * 将经纬度信息赋值给一个ArrayList * @param location * @return arraylist */ private ArrayList getConcretMessage(Location location) { ArrayList arrayList=new ArrayList(); arrayList.add(location.getProvider()+""); arrayList.add(location.getAccuracy()+""); arrayList.add(location.getAltitude()+""); arrayList.add(location.getBearing()+""); arrayList.add(location.getExtras()+""); arrayList.add(location.getSpeed()+""); arrayList.add(location.getLatitude()+""); arrayList.add(location.getLongitude()+""); return arrayList ; } /** * 使用广播将经纬度等信息传递出去 * @param location */ private void BCL(Location location) { PendingIntent pi = getPI(location); //permission check if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { return; } //第四个参数为PendingIntent locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 9000, 1000, pi); } /** * * @param location * @return 返回一个已包装数据的PendingIntent */ private PendingIntent getPI(Location location) { Intent intent = new Intent(); intent.setAction("location1"); for(int i=0;i"DATA"+i,getConcretMessage(location).get(i)); if(count>=8){ count=0; count++; }else{ count++; } } intent.putExtra("DATA",count+""); return PendingIntent.getBroadcast(getApplication(), 1000, intent, PendingIntent.FLAG_UPDATE_CURRENT); } @Override public void onStatusChanged(String provider, int status, Bundle extras) { } @Override public void onProviderEnabled(String provider) { } @Override public void onProviderDisabled(String provider) { } @Override public void onDestroy() { super.onDestroy(); Log.i(TAG, "onDestroy"); } @Override public int onStartCommand(@Nullable Intent intent, int flags, int startId) { Log.i(TAG, "onStartCommand"); startId=START_NOT_STICKY; return super.onStartCommand(intent, flags, startId); } @Override public void onCreate() { super.onCreate(); Log.i(TAG, "onCreate"); }}
3).Service类编写完毕,将Service在AndroidManifest.xml注册
<service android:name=".LocationListenerService"> <intent-filter> <action android:name="locationlistener"/> intent-filter> service>
4).编写实现类,并做数据展示
public class MainActivity extends AppCompatActivity { private boolean CL=true; TextView textView; ListView listme; private static final String TAG ="LocationListenerService" ; private BC bc=new BC(); private String[] str=new String[8]; private ArrayList nameList=new ArrayList(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initData(); initUI(); } /** * 初始化listvie数据 */ private void initData() { nameList.add("Provider :"); nameList.add("Accuracy :"); nameList.add("Altitude :"); nameList.add("Bearing :"); nameList.add("Extras :"); nameList.add("Speed:"); nameList.add("Latitude:"); nameList.add("Longitude:"); for(int i=0;i<8;i++){ str[i]="initting"; } } private void initUI() { textView=(TextView)findViewById(R.id.text2); listme=(ListView)findViewById(R.id.listme); Button text_show=(Button)findViewById(R.id.text_show); text_show.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { startServer(); } }); } @Override protected void onResume() { super.onResume(); //动态注册广播 IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction("location1"); registerReceiver(bc, intentFilter); } //自定义 BroadcastReceiver public class BC extends BroadcastReceiver { public static final String TAG="BC"; @Override public void onReceive(Context context, Intent intent) { int count=Integer.parseInt(intent.getStringExtra("DATA")); for(int i=0;i"DATA"+i); } //为数据展示所在的listview添加一个适配器 listme.setAdapter(new MyAdapter()); } } //自定义数据适配器 public class MyAdapter extends BaseAdapter{ @Override public int getCount() { return nameList.size(); } @Override public Object getItem(int position) { return nameList.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { View view=View.inflate(getApplicationContext(),R.layout.list_view,null); TextView text_name=(TextView)view.findViewById(R.id.text_name); TextView text_value=(TextView)view.findViewById(R.id.text_value); text_name.setText(nameList.get(position)); text_value.setText(str[position]); return view; } } @Override protected void onDestroy() { super.onDestroy(); //解绑广播接收者 unregisterReceiver(bc); } @Override protected void onRestart() { super.onRestart(); startServer(); } /** * 开启服务 */ public void startServer(){ Intent intent = new Intent(MainActivity.this,LocationListenerService.class); startService(intent); }}
5),MainActivity所用到的布局文件
1.activity_main.xml
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context="com.example.a15082.locationtest.MainActivity"><ListView android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/listme">ListView><Button android:layout_width="match_parent" android:padding="5dp" android:layout_height="wrap_content" android:layout_below="@+id/listme" android:id="@+id/text_show" android:text="START SERVER" />RelativeLayout>
2.list_view.xml
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/text_name"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/text_value"/>LinearLayout>
运行结果
1. 运行初始界面,点击Button开启服务
2.模拟器虚拟位置信息
3.运行结果
最后,编写过程遇到的坑,由于IntentService的特点
Intent intent = new Intent(MainActivity.this,LocationListenerService.class); startService(intent);
当服务执行完全部操作后会销毁这个服务对象。
会导致程序出现以下Warming
04-13 03:14:38.058 1469-1480/com.example.a15082.locationtest W/MessageQueue: Handler (android.location.LocationManager$ListenerTransport$1) {536d20b0} sending message to a Handler on a dead thread java.lang.RuntimeException: Handler (android.location.LocationManager$ListenerTransport$1) {536d20b0} sending message to a Handler on a dead thread at android.os.MessageQueue.enqueueMessage(MessageQueue.java:294) at android.os.Handler.sendMessageAtTime(Handler.java:473) at android.os.Handler.sendMessageDelayed(Handler.java:446) at android.os.Handler.sendMessage(Handler.java:383) at android.location.LocationManager$ListenerTransport.onLocationChanged(LocationManager.java:200) at android.location.ILocationListener$Stub.onTransact(ILocationListener.java:58) at android.os.Binder.execTransact(Binder.java:367) at dalvik.system.NativeStart.run(Native Method)
解决办法
重写Intenservice 中的onStartCommand()
@Override public int onStartCommand( Intent intent, int flags, int startId) { Log.i(TAG, "onStartCommand"); //添加这条语句改变startId的值 startId=START_NOT_STICKY; return super.onStartCommand(intent, flags, startId); }
更多相关文章
- “罗永浩抖音首秀”销售数据的可视化大屏是怎么做出来的呢?
- Nginx系列教程(三)| 一文带你读懂Nginx的负载均衡
- 不吹不黑!GitHub 上帮助人们学习编码的 12 个资源,错过血亏...
- uni-app系统目录文件上传(非只图片和视频)解决方案
- Android(安卓)UI 之实现多级列表TreeView
- Android(安卓)学习之《第一行代码》第二版 笔记(十八)调用摄像头拍
- android的网络通讯(Http通讯)封装类
- android开发中实现个性化ListView的一些概念和思路
- 直播一对一源码在Android音频开发中如何实现对讲机实时语音对话