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

在开发中遇到一个需求,需要解析拿到照片拍摄时的地址信息,在网上有很多网站提供照片上传后解析出照片的具体信息,很详细。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

android:如何从照片中获取拍摄地址信息的相关文章

怎么在Ubuntu Scope中获取location地址信息

Location信息对很多有地址进行搜索的应用来说非常重要.比如对dianping这样的应用来说,我们可以通过地址来获取当前位置的一些信息.在这篇文章中,我们来介绍如何获取Scope架构中的位置信息.这个位置信息可以对我们很多的搜索是非常重要的. 1)创建一个简单的Scope应用 我们首先打开SDK,并选择"Unity Scope"模版: 接下来,我们选择"Empty scope".这样我们就创建了我们的一个最基本的scope了. 我们可以运行我们的Scope.这是

Android下在onCreate中获取控件的宽度和高度(通过回调)

有时候需要在onCreate方法中知道某个View组件的宽度和高度等信息, 而直接调用View组件的getWidth().getHeight().getMeasuredWidth().getMeasuredHeight().getTop().getLeft()等方法是无法获取到真实值的,只会得到0. 这是因为View组件布局要在onResume回调后完成. 下面提供实现方法: 第一种: onGlobalLayout回调会在布局完成时自动调用 img1.getViewTreeObserver().

在cmd中获取ip地址和主机名

将下面的文件放到一个bat文件当中,以管理员身份运行. @echo off &setlocal enabledelayedexpansion Rem '/*========获取本机的IP地址(局域网)=========*/ echo "please wait" for /f "tokens=2 delims=:" %%b in ('ipconfig^|find /i "ip"') do set fsip=%%b echo %fsip% s

【Android Developers Training】 99. 获取联系人详细信息

注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer.android.com/training/contacts-provider/retrieve-details.html 这节课将会展示如何获取一个联系人的详细数据,比如电子邮件地址,电话号码,等等.当用户获得一个联系人后,他会想要查看他的详细信息.你可以展示给他们所有的信息,或者只展示某一特定类

高德amap 根据坐标获取的地址信息

高德地理逆地理编码接口List<List<Address>> lists = coder.getFromLocation(33.00, 116.500, 3, 3, 3, 500); Address addres = address.get(0); addres.getCountryCode=CN; addres.getCountryCode=CN; addres.getCountryName=中国; addres.getFeatureName=131乡道; addres.getL

PHP获取http头信息和CI中获取HTTP头信息的方法

CI中获取HTTP头信息的方法: $this->input->request_headers() 在不支持apache_request_headers()的非Apache环境非常有用.返回请求头(header)数组. $headers = $this->input->request_headers(); ------------------------------------------------------------------------------------------

.NET中获取IP地址

在.NET中获取一台电脑名,IP地址及当前用户名是非常简单,以下是我常用的几种方法,如果大家还有其它好的方法,可以回复一起整理: 1. 在ASP.NET中专用属性: 获取服务器电脑名:Page.Server.ManchineName 获取用户信息:Page.User 获取客户端电脑名:Page.Request.UserHostName 获取客户端电脑IP:Page.Request.UserHostAddress 2. 在网络编程中的通用方法: 获取当前电脑名:static System.Net.

Android第三方QQ登录并获取QQ用户信息

首先我们需要去腾讯开放平台申请账号,然后创建应用,地址(http://open.qq.com/) 下载我们应用中所需要的jar包,包括两个 open_sdk_r5509.jar mta_sdk-1.6.2.jar 1.加载完成将jar包放入我们的工程libs目录下 使用eclipse直接设置build path 使用Android studio 需要选中右键 --->add is library 2.做完这步之后我们在AndroidManifest.xml文件中去配置引用 <activity

[WPF] 浏览百度地图并获取经纬度地址信息

项目中需要利用登记的区域和地址在百度地图上定位,并获取该地址的经纬度. 本次功能对我来说主要难点如下:1.百度地图API的基本使用方法,请首选使用百度地图的JavaScript大众版(PS:之前使用WebAPI会导致WebBrowser浏览出现很多问题):JavaScript大众版网址:http://developer.baidu.com/map/index.php?title=jspopular2.WPF WebBrowser控件中的JavaScript与WPF的交互:3.WPF WebBro