Android 获取经纬度的服务

使用原生Android API 编写一个Service类获取经纬度信息(本文仅作为学习笔记来使用,若侵犯到您的权益,请及时与我联系,我会删除涉及侵犯到您的内容)。

一, 实现步骤

  1. 添加对应的权限
  2. 编写Service类实现获取经纬度的功能
  3. 将获取的经纬度使用广播传递到MainAtivity做数据的展示
  4. 踩过的坑

二,代码实现

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);    }

更多相关文章

  1. “罗永浩抖音首秀”销售数据的可视化大屏是怎么做出来的呢?
  2. Nginx系列教程(三)| 一文带你读懂Nginx的负载均衡
  3. 不吹不黑!GitHub 上帮助人们学习编码的 12 个资源,错过血亏...
  4. uni-app系统目录文件上传(非只图片和视频)解决方案
  5. Android(安卓)UI 之实现多级列表TreeView
  6. Android(安卓)学习之《第一行代码》第二版 笔记(十八)调用摄像头拍
  7. android的网络通讯(Http通讯)封装类
  8. android开发中实现个性化ListView的一些概念和思路
  9. 直播一对一源码在Android音频开发中如何实现对讲机实时语音对话

随机推荐

  1. 调出软键盘 挤掉标题栏咋办
  2. 样式 主题 对话框 国际化
  3. Android(安卓)7.0 https/tls证书配置问题
  4. Android中onContextItemSelected不响应
  5. Android中获取屏幕相关信息(屏幕大小,状态
  6. Android(安卓)自定义组件 方法篇
  7. Android布局(序章)
  8. AndroidStudio使用ViewPagerIndicator
  9. Android(安卓)ROM的创建和烧录
  10. android和j2me之清屏(clearScreen)