在开发中遇到一个需求,需要解析拿到照片拍摄时的地址信息,在网上有很多网站提供照片上传后解析出照片的具体信息,很详细。android也很给力,提供ExifInterface ,可以获取到拍摄照片时的很多信息。
TAG_DATETIME 时间日期
TAG_FLASH 闪光灯
TAG_GPS_LATITUDE 纬度
TAG_GPS_LATITUDE_REF 纬度参考
TAG_GPS_LONGITUDE 经度
TAG_GPS_LONGITUDE_REF 经度参考
TAG_IMAGE_LENGTH 图片长
TAG_IMAGE_WIDTH 图片宽
TAG_MAKE 设备制造商
TAG_MODEL 设备型号
TAG_ORIENTATION 方向
TAG_WHITE_BALANCE 白平衡
下面是从照片中获取经纬度,以及通过范围百度地图接口获取详细的拍摄地信息。
现在可以获取到经纬度信息,由于Google使用的经纬度格式为DMS格式,也就是度分秒格式,如果需要使用其他格式就需要转化,代码中将其转化为DD格式。
/**
* 从照片中获取经纬度
*/
public class GetLatandLng{
public GetLatandLng() {
super();
}
/**
path 为照片的路径
*/
public double[] getlocation(String path){
float output1 = 0;
float output2 = 0;
@SuppressWarnings("unused")
String context ;
Location location;
try {
ExifInterface exifInterface=new ExifInterface(path);
String latValue = exifInterface.getAttribute(ExifInterface.TAG_GPS_LATITUDE);
String latRef = exifInterface.getAttribute(ExifInterface.TAG_GPS_LATITUDE_REF);
String lngValue = exifInterface.getAttribute(ExifInterface.TAG_GPS_LONGITUDE);
String lngRef = exifInterface.getAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF);
if (latValue != null && latRef != null && lngValue != null && lngRef != null) {
try {
output1 = convertRationalLatLonToFloat(latValue, latRef);
output2= convertRationalLatLonToFloat(lngValue, lngRef);
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
}
} catch (Exception e) {
e.printStackTrace();
}
context = Context.LOCATION_SERVICE;
location=new Location(LocationManager.GPS_PROVIDER);
location.setLatitude(output1);
location.setLongitude(output2);
double lat = location.getLatitude();
double lng = location.getLongitude();
double[] f={lat,lng};
return f;
}
private static float convertRationalLatLonToFloat(
String rationalString, String ref) {
try {
String [] parts = rationalString.split(",");
String [] pair;
pair = parts[0].split("/");
double degrees = Double.parseDouble(pair[0].trim())
/ Double.parseDouble(pair[1].trim());
pair = parts[1].split("/");
double minutes = Double.parseDouble(pair[0].trim())
/ Double.parseDouble(pair[1].trim());
pair = parts[2].split("/");
double seconds = Double.parseDouble(pair[0].trim())
/ Double.parseDouble(pair[1].trim());
double result = degrees + (minutes / 60.0) + (seconds / 3600.0);
if ((ref.equals("S") || ref.equals("W"))) {
return (float) -result;
}
return (float) result;
} catch (NumberFormatException e) {
throw new IllegalArgumentException();
} catch (ArrayIndexOutOfBoundsException e) {
throw new IllegalArgumentException();
}
}
}
convertRationalLatLonToFloat方法是源码中自带的方法。
下面就需要把照片中的经纬度传给百度地图接口,但是遇到了经纬度纠偏的问题,给大家推荐一个不错的纠偏网站:
http://api.zdoz.net/Default.aspx
public class DDtoAddress {
public DDtoAddress() {
super();
}
//d数组 经纬度信息
public String GetAddress(double[] d){
//經度
String Lng=null;
//維度
String Lat=null;
BufferedReader d1;
String searchServiceURL;
URL url ;
HttpURLConnection httpConnection = null;
InputStream inputStream = null;
BufferedReader bufferedReader = null;
Address address;
//接受从网页换回的xml文件
String str1="";
double lat1 =d[0];
double lng1 =d[1];
//用未纠偏的经纬度访问纠偏网站
searchServiceURL = "http://api.zdoz.net/transgpsbd.aspx?lat="+lat1+"&lng="+lng1+"";
try {
url = new URL(searchServiceURL);
httpConnection = (HttpURLConnection) url.openConnection();
httpConnection.setRequestProperty("Content-Type", "text/plain");
httpConnection.setRequestMethod("GET");
httpConnection.setDoOutput(false);
int status = httpConnection.getResponseCode();
if (status == 200){
inputStream = httpConnection.getInputStream();
bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
//得到偏移后的经纬度
String str=bufferedReader.readLine();
String[] s = str.split(",");
String temp[]=s[0].split(":");
Lng=temp[1];
String temp1[]=s[1].split(":");
Lat=temp1[1].substring(0, temp1[1].length()-1);
}
} catch (Exception e) {
e.printStackTrace();
} finally{
try {
//关闭资源
httpConnection.disconnect();
bufferedReader.close();
inputStream.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//用纠偏后经纬度重新访问百度API
searchServiceURL = "http://api.map.baidu.com/geocoder/v2/?ak=XXXXXXXXXXXXXXXXXXX&callback=renderReverse&location="+Lat+","+Lng+"&output=xml&pois=1";
Log.i("TEST", searchServiceURL);
try {
url = new URL(searchServiceURL);
httpConnection = (HttpURLConnection) url.openConnection();
httpConnection.setRequestProperty("Content-Type", "text/plain");
httpConnection.setRequestMethod("GET");
httpConnection.setDoOutput(false);
int status = httpConnection.getResponseCode();
if (status == 200){
InputStream in = httpConnection.getInputStream();
d1 = new BufferedReader(new InputStreamReader(in));
String str;
while((str=d1.readLine()) != null){
str1 = str1+str;
}
}
//解析读取到的字符串
SAXReader sax = new SAXReader();
Document document = (Document) sax.read(new ByteArrayInputStream(str1.getBytes("UTF-8")));
//获得根元素
Element root = document.getRootElement();
Element root1 = root.element("status");
/** status
* 0 正常
1 服务器内部错误
2 请求参数非法
3 权限校验失败
4 配额校验失败
5 ak不存在或者非法
101 服务禁用
102 不通过白名单或者安全码不对
2xx 无权限
3xx 配额错误
*/
//当status=0时,做处理,并将返回的结果写入数据库中
if(root1.getText().equals("0")){
address=new Address();
Element root2 = root.element("result");
Element root3 = root2.element("formatted_address");
address.setFormatted_address(root3.getText());
Element root4 = root2.element("addressComponent");
Element root5 = root4.element("streetNumber");
address.setStreetnumber(root5.getText());
root5 = root4.element("street");
address.setStreet(root5.getText());
root5 = root4.element("district");
address.setDistrict(root5.getText());
root5 = root4.element("city");
address.setCity(root5.getText());
root5 = root4.element("province");
address.setProvince(root5.getText());
root5 = root4.element("country");
address.setCountry(root5.getText());
root5 = root4.element("countryCode");
address.setCountrycode(root5.getText());
Log.i("TEST", address.toString()+"gergergreg");
return address.toString();
}else{
//当status!=0时,做处理
}
}
catch (Exception e) {
e.printStackTrace();
}finally{
try {
httpConnection.disconnect();
bufferedReader.close();
inputStream.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return null;
}
}
上面代码中:
ak=XXXXXXXXXXXXXXXXXXX
这个为访问百度接口的密钥,就需要自己申请了
定义一个类,接受从网页返回的数据
public class Address {
String formatted_address;
String country;
String province;
String city;
String district;
String street;
String streetnumber;
String countrycode;
public Address() {
}
public Address(String formatted_address, String country, String province,
String city, String district, String street, String streetnumber,
String countrycode) {
super();
this.formatted_address = formatted_address;
this.country = country;
this.province = province;
this.city = city;
this.district = district;
this.street = street;
this.streetnumber = streetnumber;
this.countrycode = countrycode;
}
public String getFormatted_address() {
return formatted_address;
}
public void setFormatted_address(String formatted_address) {
this.formatted_address = formatted_address;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getProvince() {
return province;
}
public void setProvince(String province) {
this.province = province;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getDistrict() {
return district;
}
public void setDistrict(String district) {
this.district = district;
}
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
public String getStreetnumber() {
return streetnumber;
}
public void setStreetnumber(String streetnumber) {
this.streetnumber = streetnumber;
}
public String Countrycode() {
return countrycode;
}
public void setCountrycode(String countrycode) {
this.countrycode = countrycode;
}
@Override
public String toString() {
return country + province + city + district + street + streetnumber ;
}
}
MainActivity .java
public class MainActivity extends Activity {
//照片路径
String path="/sdcard/images/test.jpg";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/**
* 必须加入下面两句,否则报错
* android.os.NetworkOnMainThreadException
*/
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectDiskReads().detectDiskWrites().detectNetwork().penaltyLog().build());
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectLeakedSqlLiteObjects().detectLeakedClosableObjects().penaltyLog().penaltyDeath().build());
GetLatandLng getlatandlng=new GetLatandLng();
double[] d=getlatandlng.getlocation(path);
DDtoAddress getAddress=new DDtoAddress();
String address=getAddress.GetAddress(d);
if(address!=null){
Toast.makeText(MainActivity.this,address, Toast.LENGTH_LONG).show();
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
提示:访问SDcard和访问网络都需要在清单文件夹中加入相应的权限
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-10-27 05:21:30