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-傻瓜与非傻瓜 广播接 ...
随机推荐
- c常用函数
一.strtol long int strtol(const char *nptr, char **endptr, int base) strtol()会将nptr指向的字符串,根据参数base,按权 ...
- 手动启动 oracle 服务
手动启动 Oracle 服务 为了学习,我们常常会在个人PC上安装 Oracle 数据库,这大大影响了计算机的运行速度,尤其是计算机开机速度,如果 Oracle 使用频率并不是非常高,我们可以禁止 ...
- python模块之 fabric
Python模块之Fabric Fabric简介 Fabric是一个Python库,可以通过SSH在多个host上批量执行任务.你可以编写任务脚本,然后通过Fabric在本地就可以使用SSH在大量 ...
- golang使用etcd实现分布式锁
package main import ( "context" "fmt" "time" "go.etcd.io/etcd/cli ...
- Solr学习笔记(5)—— Spring Data Solr入门
一.Spring Data Solr简介 前面已经介绍了通过solrJ来操作solr,那么我们如何将Solr的应用集成到Spring中?Spring Data Solr就是为了方便Solr的开发所研制 ...
- 并发编程>>并发级别(二)
理解并发 这是我在开发者头条看到的.@编程原理林振华 有目标的提升自己会事半功倍,前行的道路并不孤独. 1.阻塞 当一个线程进入临界区(公共资源区)后,其他线程必须在临界区外等待,待进去的线程执行完成 ...
- 厉害了,七牛云 CEO 来讲架构了!
说起许式伟,你应该不陌生,他是七牛云的CEO,ECUG 社区发起人,国内 Go 语言圈的领军人物,曾就职于金山.盛大,有超过 10 年的搜索和分布式存储相关技术的研发经验. 他的个人经历颇为传奇,大学 ...
- 【性能测试】:对WebSphere中间件的监控方式
1 登录WebSphere控制台 2 选择应用.点击启动和停止来启动和停止应用 3 查看当前活动.点击要查看的项目 4 在开始监测前,先选中服务,点击启动监控将集合状态改为活动的 进入页面后,在页面 ...
- 写在学习Oracle之前
好久没有更新我的博客了,主要是因为年前换了工作.新工作比较忙,很少时间来博客园了. 作为Android开发人员,我为什么要学习Oracle数据库呢?我是非计算机专业出身,大学没有学习过任何关于数据库和 ...
- 数据库主键ID生成策略
前言: 系统唯一ID是我们在设计一个系统的时候常常会遇见的问题,下面介绍一些常见的ID生成策略. Sequence ID UUID GUID COMB Snowflake 最开始的自增ID为了实现分库 ...