android:如何从照片中获取拍摄地址信息

来源:互联网 发布:2am 2pm 知乎 编辑:程序博客网 时间:2024/04/20 14:14

在开发中遇到一个需求,需要解析拿到照片拍摄时的地址信息,在网上有很多网站提供照片上传后解析出照片的具体信息,很详细。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和访问网络都需要在清单文件夹中加入相应的权限

0 0