Android2.2下camera應用程序支持GPS信息寫入jpeg文件

 

一、概述

在Android2.2中,Camera的應用程序並不支持將GPS信息寫入到JPEG文件中,但如果要實現這個功能,有如下兩種方式:

1、修改底層camera驅動。在拍照時,一般都是使用硬件去進行JPEG編碼,這樣就需要修改JPEG編碼器,使其可以將GPS信息寫入JPEG文件的頭部,即EXIF部分。這種方式使用與手機驅動開發者。

2、修改camera應用程序。Camera應用程序本身不支持該功能,但是android系統中提供了支持該功能的類——ExifInterface。本文介紹如何使用該類進行GPS信息的寫入。這種方法的不足在於,每次寫入GPS功能,都會把原有的JPEG文件讀出,修改了Exif header部分後再寫入文件。

二、實現GPS寫入功能

首先來看看文件ImageManager.java,該文件位於:

/package/apps/Camera/src/com/android/camera/

該文件中,有個addImage()函數,其定義爲:

public static Uri addImage(ContentResolver cr, String title, long dateTaken,

            Location location, String directory, String filename,

            Bitmap source, byte[] jpegData, int[] degree) {

        。。。。。。

        String filePath = directory + "/" + filename;

        。。。。。。

        if (location != null) {

            values.put(Images.Media.LATITUDE, location.getLatitude());

            values.put(Images.Media.LONGITUDE, location.getLongitude());        

           }

       }

    return cr.insert(STORAGE_URI, values);

}

此處,當location不等於null時,表示已經開啓存儲位置的功能,並且該手機的GPS功能已開啓並且正常。在這裏,我們就可以把GPS的信息寫入JPEG文件中。其具體code如下:

public static Uri addImage(ContentResolver cr, String title, long dateTaken,

            Location location, String directory, String filename,

            Bitmap source, byte[] jpegData, int[] degree) {

        。。。。。。

        String filePath = directory + "/" + filename;

        。。。。。。

        if (location != null) {

            values.put(Images.Media.LATITUDE, location.getLatitude());

            values.put(Images.Media.LONGITUDE, location.getLongitude());

           ExifInterface exif = null;

        try {

            exif = new ExifInterface(filePath);

        } catch (IOException ex) {

            Log.e(TAG, "cannot read exif", ex);

           }

         exif.setAttribute(ExifInterface.TAG_GPS_LATITUDE, Double.toString(location.getLatitude()));        

           exif.setAttribute(ExifInterface.TAG_GPS_LONGITUDE, Double.toString(location.getLongitude()));

           try{

               if(exif != null)

              exif.saveAttributes();

           } catch (IOException ex) {

              Log.e(TAG, "Fail to exif.saveAttributes().");

           }

       }

    return cr.insert(STORAGE_URI, values);

}

 

三、分析GPS寫入功能的實現

首先看看類ExifInterface的構造函數,其位於:

/framework/base/media/java/android/media/ ExifInterface.java

其具體實現爲:

    public ExifInterface(String filename) throws IOException {

        mFilename = filename;

        loadAttributes();

}

其功能是從指定的文件中獲取其Exif信息。函數loadAttributes()的定義爲:

    private void loadAttributes() throws IOException {

        // format of string passed from native C code:

        // "attrCnt attr1=valueLen value1attr2=value2Len value2..."

        // example:

        // "4 attrPtr ImageLength=4 1024Model=6 FooImageWidth=4 1280Make=3 FOO"

        mAttributes = new HashMap<String, String>();

 

        String attrStr;

        synchronized (sLock) {

            attrStr = getAttributesNative(mFilename);

        }

        ……

}

該函數從文件中讀取Exif信息,並將其寫入mAttributes中。函數

getAttributesNative(mFilename),調用了JNI接口,其定義位於:

/external/jhead/main.c

static JNINativeMethod methods[] = {

  {"saveAttributesNative", "(Ljava/lang/String;Ljava/lang/String;)V", (void*)saveAttributes },

  {"getAttributesNative", "(Ljava/lang/String;)Ljava/lang/String;", (void*)getAttributes },

  {"appendThumbnailNative", "(Ljava/lang/String;Ljava/lang/String;)Z", (void*)appendThumbnail },

  {"commitChangesNative", "(Ljava/lang/String;)V", (void*)commitChanges },

  {"getThumbnailNative", "(Ljava/lang/String;)[B", (void*)getThumbnail },

};

 

函數setAttribute()的實現如下:

    public void setAttribute(String tag, String value) {

        mAttributes.put(tag, value);

}

向mAttributes寫入對應的項,比如經度和緯度信息。

最重要的函數saveAttributes(),它也是調用JNI接口。它負責將所有的Exif項寫入到JPEG文件中。由於時間關係,就不做介紹了,具體代碼請大家自己看,有問題的話,一起討論。

發佈了53 篇原創文章 · 獲贊 23 · 訪問量 43萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章