Android学习笔记(2)----LocationManager的使用
今天使用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的使用的更多相关文章
- Android 学习笔记之Volley(七)实现Json数据加载和解析...
学习内容: 1.使用Volley实现异步加载Json数据... Volley的第二大请求就是通过发送请求异步实现Json数据信息的加载,加载Json数据有两种方式,一种是通过获取Json对象,然后 ...
- Android学习笔记进阶之在图片上涂鸦(能清屏)
Android学习笔记进阶之在图片上涂鸦(能清屏) 2013-11-19 10:52 117人阅读 评论(0) 收藏 举报 HandWritingActivity.java package xiaos ...
- android学习笔记36——使用原始XML文件
XML文件 android中使用XML文件,需要开发者手动创建res/xml文件夹. 实例如下: book.xml==> <?xml version="1.0" enc ...
- Android学习笔记之JSON数据解析
转载:Android学习笔记44:JSON数据解析 JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,采用完全独立于语言的文本格式,为Web应用开发提供了一种 ...
- udacity android 学习笔记: lesson 4 part b
udacity android 学习笔记: lesson 4 part b 作者:干货店打杂的 /titer1 /Archimedes 出处:https://code.csdn.net/titer1 ...
- Android学习笔记36:使用SQLite方式存储数据
在Android中一共提供了5种数据存储方式,分别为: (1)Files:通过FileInputStream和FileOutputStream对文件进行操作.具体使用方法可以参阅博文<Andro ...
- Android学习笔记之Activity详解
1 理解Activity Activity就是一个包含应用程序界面的窗口,是Android四大组件之一.一个应用程序可以包含零个或多个Activity.一个Activity的生命周期是指从屏幕上显示那 ...
- Pro Android学习笔记 ActionBar(1):Home图标区
Pro Android学习笔记(四八):ActionBar(1):Home图标区 2013年03月10日 ⁄ 综合 ⁄ 共 3256字 ⁄ 字号 小 中 大 ⁄ 评论关闭 ActionBar在A ...
- 【转】Pro Android学习笔记(九八):BroadcastReceiver(2):接收器触发通知
文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注册等附加条件.转载须注明出处:http://blog.sina.com.cn/flowingflying或作者@恺风Wei-傻瓜与非傻瓜 广播接 ...
随机推荐
- ES6之新增const命令使用方法
hi,我又回来了,今天学习一下const命令. 声明一个常量 const声明一个只读常量,一旦声明,常量的值便不可改变. 例子如下: const food = 12; food = 23; // Un ...
- jmeter的non-gui模式的使用
jmeter的non-gui模式的使用,待补充
- Linux 线程调度策略与线程优先级
Linux内核的三种调度策略 SCHED_OTHER 分时调度策略. 它是默认的线程分时调度策略,所有的线程的优先级别都是0,线程的调度是通过分时来完成的.简单地说,如果系统使用这种调度策略,程序将无 ...
- Spring事务杂谈
1. 什么是事务 事务就是以一种可控的方式,对资源进行的一组操作,保证了资源在事务前后,始终应处于被期待的正确的状态.比如不会受到宕机等原因的影响.事务本身,具有如下4种属性-ACID.(所以说事务是 ...
- PHP反序列化漏洞新攻击面(BlackHat 2018)
0x00 前言 入职以来好久没有写过文章了,入职的时间里也和师傅们学到了很多,认识了很多的新朋友.最近因为BlackHat 黑客大会的一个议题,PHP反序列化漏洞利用被挖掘出新的攻击面.这里本着记 ...
- Axis2 Web Service Development & Deployment Guide(Axis2使用)
主要内容: 记录关于Axis2的使用,通过WSDL文件生成Web service的客户端和服务器端的过程. 目录: Requirement(必备工具) Development - Client Gen ...
- SASS的安装和转换为CSS的方法
http://www.cnblogs.com/52css/archive/2012/08/19/sass-how-to-install-and-use.html SASS的安装方法: 1.先安装Rub ...
- redis持久化之 aof日志
aof就是把执行的命令写到文本文件里面 aof使用过程 第一步: 修改配置文件,并启动server 第二步, 当前目录下面会生成一个 appendonly.aof文件,但是是空的 去客户端 开始操作后 ...
- 如何查看yum安装路径
#yum install hdf5 #rpm -qa|grep hdf5 hdf5-1.8.7-1.el6.rf.x86_64 #rpm -ql hdf5-1.8.7-1.el6.rf.x86_64
- Struts2 Validate
1.自定义action继承ActionSupport 2.复写validate方法,因为ActionSupport实现了Validate这个借口,而这个借口中定义了validate方法 3.当请求时, ...