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()函数,其定义为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
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

其具体实现为:

1
2
3
4
5
6
7
public ExifInterface(String filename) throws IOException {
 
        mFilename = filename;
 
        loadAttributes();
 
}

其功能是从指定的文件中获取其Exif信息。函数loadAttributes()的定义为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
   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

1
2
3
4
5
6
7
8
9
10
11
12
13
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()的实现如下:

1
2
3
4
5
public void setAttribute(String tag, String value) {
 
        mAttributes.put(tag, value);
 
}

向mAttributes写入对应的项,比如经度和纬度信息。

最重要的函数saveAttributes(),它也是调用JNI接口。它负责将所有的Exif项写入到JPEG文件中。由于时间关系,就不做介绍了,具体代码请大家自己看,有问题的话,一起讨论。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值