在开发中遇到一个需求,需要解析拿到照片拍摄时的地址信息,在网上有很多网站提供照片上传后解析出照片的具体信息,很详细。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和访问网络都需要在清单文件夹中加入相应的权限
版权声明:本文为博主原创文章,未经博主允许不得转载。