今天使用Android的LocationManager制作了一款获取当前经纬坐标位置的软件。

  LocationManager获取的只是经纬坐标点,为了解析出当前经纬坐标点的实际位置,可以使用Google提供的 Geocoding API 服务。

    谷歌提供了一套 Geocoding API,使用它的话可以完成反向地理编码的工作,只不过它的用法稍微复杂了一些,但稳定性要比 GeoCoder 强得多。本小节中我们只是学习一下 GeocodingAPI 的简单用法, 更详细的用法请参考官方文档: https://developers.google.com/maps/documentation/geocoding/

  GeocodingAPI 的工作原理并不神秘,其实就是利用了 HTTP 协议。
  在手机端我们可以向谷歌的服务器发起一条 HTTP 请求,并将经纬度的值作为参数一同传递过去,然后服务器会帮我们将这个经纬值转换成看得懂的位置信息,再将这些信息返回给手机端,最后手机端去解析服务器返回的信息,并进行处理就可以了。
  Geocoding API 中规定了很多接口,其中反向地理编码的接口如下:
http://maps.googleapis.com/maps/api/geocode/json?latlng=40.714224,-73.961452&sensor=true_or_false
  我们来仔细看下这个接口的定义, 其中 http://maps.googleapis.com/maps/api/geocode/ 是固定的,表示接口的连接地址。json 表示希望服务器能够返回 JSON 格式的数据,这里也可以指定成 xml。latlng=40.714224,-73.96145 表示传递给服务器去解码的经纬值是北纬 40.714224度,西经 73.96145 度。 sensor=true_or_false 表示这条请求是否来自于某个设备的位置传感器,通常指定成 false 即可。

  如果发送

http://maps.googleapis.com/maps/api/geocode/json?latlng=40.714224,-73.96145&sensor=false

这样一条请求给 服务器,我们将会得到一段非常长的 JSON 格式的数据,其中会包括如下部分内容:

"formatted_address" : "277 Bedford Avenue, 布鲁克林纽约州 11211美国"
  从这段内容中我们就可以看出北纬 40.714224 度,西经 73.96145 度对应的地理位置是在哪里了。如果你想查看服务器返回的完整数据,在浏览器中访问上面的网址即可。
这样的话,使用 Geocoding API 进行反向地理编码的工作原理你就已经搞清楚了,那么难点其实就在于如何从服务器返回的数据中解析出我们想要的那部分信息了。因而软件的一个关键点就在于JSON数据的解析。

代码如下:

//activity_main.xml

//activity_main.xml

<LinearLayout 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"
android:orientation="vertical"
> <TextView
android:id="@+id/position_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello"
/>
<TextView
android:id="@+id/position_plain_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/> </LinearLayout>

界面如下:

//MainActivity.java

//MainActivity.java

package com.example.location;

import java.util.List;
import org.json.JSONArray;
import org.json.JSONObject;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.TextView;
import android.widget.Toast; public class MainActivity extends Activity {
private static final String TAG="POSITION";
public static final int SHOW_LOCATION=0;//更新文字式的位置信息
public static final int SHOW_LATLNG=1; //更新经纬坐标式的位置信息
private TextView positionTextView;
private TextView positionLatLng;
private LocationManager locationManager;
private String provider; private Handler handler=new Handler(){
@SuppressLint("HandlerLeak")
@Override
public void handleMessage(Message message){
switch(message.what){
case SHOW_LOCATION:
Log.d(TAG, "showing the positio>>>>>");
String currentPosition=(String)message.obj;
positionTextView.setText(currentPosition);
Log.d(TAG, "Has show the position...>>>>....");
break;
case SHOW_LATLNG:
String latlng=(String)message.obj;
positionLatLng.setText(latlng);
default:
break;
}
}
}; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
positionTextView=(TextView)findViewById(R.id.position_text_view);
positionLatLng=(TextView)findViewById(R.id.position_plain_text);
locationManager=(LocationManager)getSystemService(Context.LOCATION_SERVICE);
//获取所有可用的位置提供器
List<String>providerList=locationManager.getProviders(true);
if(providerList.contains(LocationManager.GPS_PROVIDER)){
provider=LocationManager.GPS_PROVIDER;
}
else if(providerList.contains(LocationManager.NETWORK_PROVIDER)){
provider=LocationManager.NETWORK_PROVIDER;
}
else{
//当没有可用的位置提供器时,弹出Toast提示用户
Toast.makeText(this, "No Location provider to use", Toast.LENGTH_SHORT).show();
return;
}
Location location=locationManager.getLastKnownLocation(provider);
if(location!=null){
//显示当前设备的位置信息
Log.d(TAG, "location!=null");
showLocation(location);
}
locationManager.requestLocationUpdates(provider, 1000, 1, locationListener);
Log.d(TAG, "Running....");
} protected void onDestroy(){
super.onDestroy();
if(locationManager!=null){
//关闭程序时将监听移除
locationManager.removeUpdates(locationListener);
}
}
//LocationListener 用于当位置信息变化时由 locationManager 调用
LocationListener locationListener=new LocationListener(){ @Override
public void onLocationChanged(Location location) {
// TODO Auto-generated method stub
//更新当前设备的位置信息
showLocation(location);
} @Override
public void onProviderDisabled(String provider) {
// TODO Auto-generated method stub } @Override
public void onProviderEnabled(String provider) {
// TODO Auto-generated method stub } @Override
public void onStatusChanged(String provider, int status, Bundle extras) {
// TODO Auto-generated method stub } }; private void showLocation(final Location location){
//显示实际地理位置
//开启线程来发起网络请求
new Thread(new Runnable(){ @Override
public void run() {
// TODO Auto-generated method stub
try{
String request="http://maps.googleapis.com/maps/api/geocode/json?latlng=";
request+=location.getLatitude()+","+location.getLongitude()+"&sensor=false";
String response=HttpUtil.sendHttpRequest(MainActivity.this,request);
parseJSONResponse(response); }
catch(Exception e){
Log.d(TAG, "showLocation: the inptuStream is wrong!");
e.printStackTrace();
}
} }).start();
//显示经纬度坐标
new Thread(new Runnable(){ @Override
public void run() {
// TODO Auto-generated method stub
String position="";
position="Latitude="+location.getLatitude()+"\n"
+"Longitude="+location.getLongitude();
Message msg=new Message();
msg.what=SHOW_LATLNG;
msg.obj=position;
handler.sendMessage(msg);
} }).start();
} //解析JSON数据
private void parseJSONResponse(String response){
try{
Log.d(TAG, "parseJSONResponse: getting the jsonObject...");
JSONObject jsonObject=new JSONObject(response);
//获取results节点下的位置
Log.d(TAG, "parseJSONResponse: Getting the jsongArray...");
JSONArray resultArray=jsonObject.getJSONArray("results");
Log.d(TAG, "parseJSONResponse: Got the JSONArray...");
if(resultArray.length()>0){
JSONObject subObject=resultArray.getJSONObject(0);
//取出格式化后的位置信息
String address=subObject.getString("formatted_address");
Message message=new Message();
message.what=SHOW_LOCATION;
message.obj="您的位置:"+address;
Log.d(TAG, "showLocation:Sending the inputStream...");
handler.sendMessage(message);
}
}
catch(Exception e){
Log.d(TAG, "parseJSONResponse: something wrong");
e.printStackTrace();
} } }

通用类HttpUtil.java(提供获取Http请求的结果的静态方法 sendHttpRequest)

//HttpUtil.java

//HttpUtil.java

package com.example.location;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import android.content.Context;
import android.util.Log; public class HttpUtil {
private static final String TAG="POSITION";
public static String sendHttpRequest(Context context,String address){
HttpURLConnection connection=null;
try{
URL url=new URL(address);
Log.d(TAG, "HttpUtil: request="+address);
connection=(HttpURLConnection)url.openConnection();
connection.setRequestMethod("GET");
connection.setRequestProperty("Accept-Language", "zh-CN");
connection.setConnectTimeout(8000);
connection.setReadTimeout(8000);
Log.d(TAG, "HttpUtil: getting the inputStream...");
InputStream in=connection.getInputStream();
Log.d(TAG, "HttpUtil: got the inputStream...");
//下面对获取到的流进行读取
BufferedReader reader=new BufferedReader(new InputStreamReader(in));
StringBuilder response=new StringBuilder();
String line;
while((line=reader.readLine())!=null){
response.append(line);
}
Log.d(TAG, "HttpUtil: Got the response...");
return response.toString();
}
catch(Exception e){
e.printStackTrace();
Log.d(TAG, "HttpUtil: Some thing wrong....");
return e.getMessage();
}
finally{
if(connection!=null){
connection.disconnect();
}
}
} }

因为软件使用了位置服务,所以要在Manifest.xml文件中添加使用位置服务的 uses-permission:

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

//Location Manifest.xml

//Location Manifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.location"
android:versionCode="1"
android:versionName="1.0" > <uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="21" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> <application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application> </manifest>

但是调试软件的时候,发现HttpUtil.sendHttpRequest() 方法总是在 getInputStream() 那一步出现 Exception。百思终得其解:原来忘记添加使用网络功能的权限了。添加如下:

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

//Location Manifest.xml

//Location Manifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.location"
android:versionCode="1"
android:versionName="1.0" > <uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="21" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> <application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application> </manifest>

现在软件就可以正常运行了。

值得注意的是,这里需要使用Google提供的Geocoding服务,而目前Google的网站一般都还在墙外,手机需要翻墙才能获得Geocoding的功能。恰好自己之前购买了VPN,就先用笔记本电脑连接上VPN,在浏览器中确定可以通过http://maps.googleapis.com/maps/api/geocode/json?latlng=40.714224,-73.961452&sensor=true_or_false这样的地址获取位置服务,然后用笔记本开启WiFi,手机连接上这个开通了VPN的WiFi,就可以使用Geocoding服务了。

Android学习笔记(2)----LocationManager的使用的更多相关文章

  1. Android 学习笔记之Volley(七)实现Json数据加载和解析...

    学习内容: 1.使用Volley实现异步加载Json数据...   Volley的第二大请求就是通过发送请求异步实现Json数据信息的加载,加载Json数据有两种方式,一种是通过获取Json对象,然后 ...

  2. Android学习笔记进阶之在图片上涂鸦(能清屏)

    Android学习笔记进阶之在图片上涂鸦(能清屏) 2013-11-19 10:52 117人阅读 评论(0) 收藏 举报 HandWritingActivity.java package xiaos ...

  3. android学习笔记36——使用原始XML文件

    XML文件 android中使用XML文件,需要开发者手动创建res/xml文件夹. 实例如下: book.xml==> <?xml version="1.0" enc ...

  4. Android学习笔记之JSON数据解析

    转载:Android学习笔记44:JSON数据解析 JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,采用完全独立于语言的文本格式,为Web应用开发提供了一种 ...

  5. udacity android 学习笔记: lesson 4 part b

    udacity android 学习笔记: lesson 4 part b 作者:干货店打杂的 /titer1 /Archimedes 出处:https://code.csdn.net/titer1 ...

  6. Android学习笔记36:使用SQLite方式存储数据

    在Android中一共提供了5种数据存储方式,分别为: (1)Files:通过FileInputStream和FileOutputStream对文件进行操作.具体使用方法可以参阅博文<Andro ...

  7. Android学习笔记之Activity详解

    1 理解Activity Activity就是一个包含应用程序界面的窗口,是Android四大组件之一.一个应用程序可以包含零个或多个Activity.一个Activity的生命周期是指从屏幕上显示那 ...

  8. Pro Android学习笔记 ActionBar(1):Home图标区

     Pro Android学习笔记(四八):ActionBar(1):Home图标区 2013年03月10日 ⁄ 综合 ⁄ 共 3256字 ⁄ 字号 小 中 大 ⁄ 评论关闭 ActionBar在A ...

  9. 【转】Pro Android学习笔记(九八):BroadcastReceiver(2):接收器触发通知

    文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注册等附加条件.转载须注明出处:http://blog.sina.com.cn/flowingflying或作者@恺风Wei-傻瓜与非傻瓜 广播接 ...

随机推荐

  1. 【性能测试】:LR中解决接口请求中包含中文字符,服务器不识别的问题

    在LR中,直接写的接口请求,如果请求字段包含中文字段,服务器会不识别,这个时候就要用到lr_convert_string_encoding这个函数: 具体用法: lr_convert_string_e ...

  2. Web安全之CSRF攻击的防御措施

    Web安全之CSRF攻击的防御措施   CSRF是什么? Cross Site Request Forgery,中文是:跨站点请求伪造. CSRF攻击者在用户已经登录目标网站之后,诱使用户访问一个攻击 ...

  3. python-TCP模拟ftp文件传输

    #!/usr/bin/python #coding=utf-8 #server from socket import* import sys,os def command(): l=[ "W ...

  4. MongoDB日志文件过大

    MongoDB日志文件过大 MongoDB启动的时候指定了--logpath为一个日志文件.随着时间此文件会变得越来越大,达到好几个G. 因为不想让MongoDB进程重新启动,所以不能停止进程删除此文 ...

  5. Struts1原理解析

    1.浏览器发送http请求->web服务器. 2.web服务器将 请求进行解析. 3.web服务器解析后将请求转发给ActionServelet(总队长). 3.查询struts-config. ...

  6. java中,方法可以访问他的类对象的任何私有特性

    java中,方法可以访问他的类对象的任何私有特性 读一本书(Core Java for the Impatient)时,发现这个注意,以前的时候没有在意,今天仔细想想发现记忆不深刻.记录一下 下面代码 ...

  7. 关于docker的理解随记

    1.容器其实不是什么新技术,说白了就是namespace对资源进行隔离,再加UFS实现分层镜像,以及cgroup实现资源限制.这些技术,都是linux中已有的技术,而且有些技术很早之前就有了. 2.上 ...

  8. js if和switch,==和===

    今天改插件BoxScroll的时候,因为if里面的条件判断多于两个,于是立马想着改写switch.改到一半,忽然记起来JSHint等代码质量检测工具中的一个要求,用===替换==,不用不可靠的强制转型 ...

  9. 入门系列之在Ubuntu上安装Drone持续集成环境

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由小铁匠米兰的v 发表于云+社区专栏 介绍 Drone是一个流行的持续集成和交付平台.它集成了许多流行的版本控制存储库服务,如GitHu ...

  10. System.Web.Caching.Cache类 缓存 各种缓存依赖(转)

    转自:http://www.cnblogs.com/kissdodog/archive/2013/05/07/3064895.html Cache类,是一个用于缓存常用信息的类.HttpRuntime ...