2011년 11월 30일 수요일

android OpenJDK vs Sun JDK build

Ubuntu 11.10 업데이트 후 자동으로 설치되었는지 확인은 되지 않지만 OpenJDK가 설치 되어 있습니다.

android build시 gingerbread까지는 OpenJDK로 build하여도 문제가 없는데 ICS build시 아래와 같은 에러가 발생합니다.


error: error reading out/target/common/obj/JAVA_LIBRARIES/core-tests_intermediates/javalib.jar; invalid header field
1 error
make: *** [out/target/common/obj/APPS/FrameworksCoreSystemPropertiesTests_intermediates/classes-full-debug.jar] 오류 41

googling 하여 보니 OpenJDK로 build는 가능하나 Sun JDK를 사용하기를 권장하는 것 같습니다.

synatic에서 OpenJDK를 삭제하시고 Sun JDK로 설치하시고


[~/projects/ICS]$ sudo update-alternatives --config jar
[sudo] password for codewalker:
대체 항목 jar에 대해 (/usr/bin/jar 제공) 2개 선택이 있습니다.

  선택       경로                           우선순  상태
------------------------------------------------------------
* 0            /usr/bin/fastjar                  100       자동 모드
  1            /usr/bin/fastjar                  100       수동 모드
  2            /usr/lib/jvm/java-6-sun/bin/jar   63        수동 모드

기본 사항[*]을 사용하려면 엔터, 다른 것을 사용하려면 번호를 입력하십시오: 2

jar도 위와 같이 java-6-sun/bin/jar를 선택하십시오.



http://groups.google.com/group/android-building/browse_thread/thread/f82cc424d451e409/91e29dac50ee1970?show_docid=91e29dac50ee1970

아직도 ICS AOSP가 빌드가 되지 않고 있습니다.


Preparing output jar [/home/codewalker/projects/ICS/out/target/common/obj/APPS/WAPPushManager_intermediates/proguard.classes.jar]
  Copying resources from program jar [/home/codewalker/projects/ICS/out/target/common/obj/APPS/WAPPushManager_intermediates/classes.jar]
target Java: FrameworksServicesTests (out/target/common/obj/APPS/FrameworksServicesTests_intermediates/classes)
target Dex: android.core.tests.libcore.package.com.no-core-tests-res
target Dex: android.core.tests.libcore.package.dalvik.no-core-tests-res
target Dex: android.core.tests.libcore.package.libcore.no-core-tests-res
target Dex: android.core.tests.libcore.package.org.no-core-tests-res
target Dex: android.core.tests.libcore.package.sun.no-core-tests-res
target Dex: android.core.tests.libcore.package.tests.no-core-tests-res

이 단계에서 top을 해 보면 java가 몇개 돌고 있고 메모리를 거의 다 사용하고 있어서 시스템이 거의 동작하지 않고 build 역시 안되는 것 같습니다. 여기서 해결이 안되네요. ㅡㅡ;

https://groups.google.com/group/android-building/browse_thread/thread/1d01d0cd635c7f9e

여기 설명대로 -j 옵션을 없애니 컴파일이 계속되네요. 이해가 안가네요.

결과 Ubuntu 11.10 최신 버전을 사용하고 있었는데 OS가 문제가 있어서 다시 설치해야 하서 결국 Google에서 recommend하는 10.04로 재설치 하였습니다.

그런데 package/app들 build하다가 아래 링크의 설명 처럼 에러가 발생합니다.


fix "bad class file error" android build error



http://rxwen.blogspot.com/2011/08/fix-bad-class-file-error-android-build.html

eclipse를 설치하고 나면 jar가 fastjar로 바뀝니다.
그래서 결국 android ICS build 하려면 jar를 다시 설정해 주셔야 합니다.

2011년 11월 29일 화요일

2011년 11월 28일 월요일

ubuntu 11.10에서 android(Gingerbread) build error...


ubuntu 11.10으로 업데이트 후 gcc 버전을 확인 해 보면 아래와 같습니다.


[~/projects/ICS/device/samsung]$ gcc --version
gcc (Ubuntu/Linaro 4.6.1-9ubuntu3) 4.6.1
Copyright (C) 2011 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

그래서 android build 시 두가지 에러가 발생합니다.


In file included from external/oprofile/libpp/arrange_profiles.cpp:24:0:
external/oprofile/libpp/format_output.h:94:22: error: reference ‘counts’ cannot be declared ‘mutable’ [-fpermissive]
make: *** [out/host/linux-x86/obj/STATIC_LIBRARIES/liboprofile_pp_intermediates/arrange_profiles.o] 오류 1
make: *** 끝나지 않은 작업을 기다리고 있습니다....
make: *** [out/host/linux-x86/obj/STATIC_LIBRARIES/liboprofile_pp_intermediates/format_output.o] 오류 1
true


frameworks/base/libs/utils/Android.mk
LOCAL_CFLAGS += -DLIBUTILS_NATIVE=1 $(TOOL_CFLAGS)
LOCAL_CFLAGS += -DLIBUTILS_NATIVE=1 $(TOOL_CFLAGS) -fpermissive





error: "_FORTIFY_SOURCE" redefined [-Werror]



build/core/combo/HOST_linux-x86.mk line 61:

-HOST_GLOBAL_CFLAGS += -D_FORTIFY_SOURCE=0

+HOST_GLOBAL_CFLAGS += -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0

2011년 11월 24일 목요일

android에서 USB Mass Storage 사용하기

ODROID-7/A에 USB Host가 있습니다.

거기에 USB 저장장치를 연결하여 자동으로 mnt/sdcard/external_storage란 폴더에 자동으로 마운트가 되도록 수정해 보려고 합니다.

ODROID-A에는 두개의 mmc가 있어서 galaxy s처럼 추가 외부 저장장치를 지원합니다.

vold와 MountService.java를 수정하였습니다.

vold.fstab에 bus node를 등록하면 UMS까지 지원하려고 했지만 usb mass 장치를 붙일때 마다 bus node의 인덱싱이 host1, host2 처럼 증가합니다.

vold의 구조가 동적 증가하는 장치를 지원하지 않는 구조 입니다.

fstab에 등록되어 있는 노드 객체를 만들고 등록된 Volume이 NetlinkEvent의 DEVPATH와 동일하면 처리합니다. 따라서 USB Host에 연결하는 장치와 같이 bus 이름이 증가하는 구조에는 적용이 안됩니다.

그리서 vold에서 강제로 mount 하도록 해 봤습니다.

kernel에 USB Mass Storage support를 추가 한다.

     <*>   USB Mass Storage support   



그리고 system/vold/VolumeManager.cpp에 handleBlockEvent() 함수를 다음과 같이 수정합니다.


bool usb_storage_mounted = false;
bool second_netlinkevent = false;


void VolumeManager::handleBlockEvent(NetlinkEvent *evt) {
    const char *devpath = evt->findParam("DEVPATH");

    /* Lookup a volume to handle this device */
    VolumeCollection::iterator it;
    bool hit = false;
    for (it = mVolumes->begin(); it != mVolumes->end(); ++it) {
        if (!(*it)->handleBlockEvent(evt)) {
#ifdef NETLINK_DEBUG
            SLOGD("Device '%s' event handled by volume %s\n", devpath, (*it)->getLabel());
#endif
            hit = true;
            break;
        }
    }

    if (!hit) {
#ifdef NETLINK_DEBUG
        SLOGW("No volumes handled block event for '%s'", devpath);
#endif


        if (second_netlinkevent) {
            second_netlinkevent = false;
            return;
        }

        char *usb_mass_node = "/devices/platform/s5p-ehci/usb";
        if (usb_storage_mounted) {
            umount("/mnt/sdcard/external_storage");
            usb_storage_mounted = false;
            SLOGE("unmounted USB Mass Storage");
        } else {
            int len = strlen(usb_mass_node);
            if (strncmp(devpath, usb_mass_node, len) == 0) {
                usleep(5000);
                if (Fat::doMount("/dev/block/sda1", "/mnt/sdcard/external_storage", false, false, false,
                 1000, 1015, 0702, true)) {
                    SLOGE("%s failed to mount via VFAT (%s)\n", devpath, strerror(errno));
                } else {
                    SLOGE("mounted USB Mass Storage");
                    usb_storage_mounted = true;
                }
            } else {
                SLOGE("not USB Mass Storage");
            }
        }

        second_netlinkevent = true;
    }

코드를 조금 설명 드리면 USB Mass는 event가 두번 발생하여 second_netlinkevent를 통해 한번만 처리되도록 하였습니다.

usleep은 event가 발생시점에는 node가 없을 수 있기 때문에 대기 하였다 mount 시킵니다.

devpath가 "/devices/platform/s5p-ehci/usb" 까지 동일하고 usb1,2,3... 이렇게 증가 하기 때문에 여기까지 같다면 usb mass storage 장치가 연결된 걸로 처리 합니다.

물론 init.rc에 external_storage 노드를 처리하여야 합니다.

 40 # create mountpoints
 41     mkdir /mnt 0775 root system
 42     mkdir /mnt/sdcard 0000 system system
 43     mkdir /mnt/sdcard/external_storage 0000 system system
 44 
 45 # Create cgroup mount point for cpu accounting
 46     mkdir /acct
 47     mount cgroup none /acct cpuacct
 48     mkdir /acct/uid
 49 
 50 # Backwards Compat - XXX: Going away in G*
 51     symlink /mnt/sdcard /sdcard
 52     symlink /mnt/sdcard/external_storage /sdcard1

그리고 vold에서 external_storage를 만드는 코드를 추가 합니다.

int CommandListener::VolumeCmd::runCommand(SocketClient *cli,
                                                      int argc, char **argv) {
    dumpArgs(argc, argv, -1);

    if (argc < 2) {
        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing Argument", false);
        return 0;
    }

    VolumeManager *vm = VolumeManager::Instance();
    int rc = 0;

    if (!strcmp(argv[1], "list")) {
        return vm->listVolumes(cli);
    } else if (!strcmp(argv[1], "debug")) {
        if (argc != 3 || (argc == 3 && (strcmp(argv[2], "off") && strcmp(argv[2], "on")))) {
            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: volume debug ", false);
            return 0;
        }
        vm->setDebug(!strcmp(argv[2], "on") ? true : false);
    } else if (!strcmp(argv[1], "mount")) {
        if (argc != 3) {
            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: volume mount ", false);
            return 0;
        }
        rc = vm->mountVolume(argv[2]);
        //codewalker
        mkdir("/mnt/sdcard/external_storage", 0777);
    } else if (!strcmp(argv[1], "unmount")) {
        if (argc < 3 || argc > 4 || (argc == 4 && strcmp(argv[3], "force"))) {
            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: volume unmount [force]", false);
            return 0;
        }

        bool force = false;
        if (argc >= 4 && !strcmp(argv[3], "force")) {



이렇게 하면 Media Scan이 안되는 문제와 UMS가 안되는 문제가 있습니다.
Astro FileManager 같은데서 직접 폴더를 열어서 사용하는 상황에 맞겠죠.

그리고 여럿 예외 처리가 필요할 걸로 판단됩니다.

2011년 11월 23일 수요일

ODROID-7에 android ICS(4.0.3_r1, IML74K) 올리기



odroid7 kernel을 준비 한다.


http://com.odroid.com/sigong/nf_file_board/nfile_board_view.php?keyword=&bid=41

아래 경로에서 kernel 소스를 다운 받는다.

https://github.com/Kwiboo/kernel_samsung_crespo/tree/master/drivers/gpu

drivers/gpu 폴더을 odroid7 kernel에 덮어쓴다.

git로 부터 최신 android 소스를 받는다.


repo init -u https://android.googlesource.com/platform/manifest -b android-4.0.1_r1.2


repo sync





아래 링크에서 odroid7으로 빌드가 가능한도록 수정한 폴더들을 받아 device와 vendor를 덮어쓴다.


http://dl.dropbox.com/u/4485660/ICS.tar.gz




vendor의 파일들은 아래 링크에서 받은 Nexus S의 ICS ROM에서 얻은 것 들이다.


http://www.multiupload.com/F0F156G363

crespo project를 지운다.

rm -rf device/samsung/crespo*

chmod u+x device/hardkerenl/odroid7/build_android.sh


안드로이드를 빌드한다.


device/hardkerenl/odroid7/build_android.sh


build가 완료되면 odroid-7 처럼 f-flash에 복사하고 zImage와 ramdisk-uboot.img를 fastboot로 write한다.














아래 소스를 고치면 마우스 없이 touch까지 가능합니다.

kernel/drivers/input/touchscreen/odroid7_MT_touch_portrait.c


169                 input_sync(hkc1xx_touch.driver);
170 
171 //codewalker
172                 input_mt_sync(hkc1xx_touch.driver);
173 
174                 input_sync(hkc1xx_touch.driver);
175 176 177 #if defined(DEBUG_HKC1XX_TOUCH_MSG) 178 printk("%s : Penup event send[x = %d, y = %d]\n", __FUNCTION__, hkc1xx_touch.x, hkc1xx_touch.y); 179 #endif




소리가 나오게 하는 방법은 ICS ROM에서 두 파일을 odroid7으로 이름을 바꿔서 넣어 주시면 됩니다.


/system/lib/hw/audio.primary.herring.so 를 audio.primary.odroid7.so
/system/lib/hw/audio_policy.herring.so 를 audio_policy.odroid7.so














wifi 가능 하도록 수정 방법



device/hardkernel/odroid7/BoardConfigCommon.mk


71 #WIFI_DRIVER_MODULE_ARG := "firmware_path=/vendor/firmware/fw_bcm4329.bin nvram_path=/vendor/firmware/nvram_net.txt iface_name=wlan" 72 WIFI_DRIVER_MODULE_ARG := "iface_name=wlan firmware_path=/vendor/firmware/fw_bcm4329.bin nvram_path=/vendor/firmware/nvram"

WIFI_DRIVER_MODULE_ARG를 수정하고 odroid7dml fw_bcm4329.bin, nvram을 해당 위치에 복사합니다.




hardware/libhardware_legacy/wifi/wifi.c


102 103 #define WIFI_WAKEUP_CTL_FP "/sys/devices/platform/hkc1xx-sysfs/wifi_wakeup" // 1 -> wakeup on 104 #define WIFI_REG_CTL_FP "/sys/devices/platform/hkc1xx-sysfs/wifi_reg" // 1 -> reg on 105 #define WIFI_RESET_CTL_FP "/sys/devices/platform/hkc1xx-sysfs/wifi_reset" // 1 -> reset on 106 107 int wifi_set_module_status (char *ctl_fp, unsigned char status); 108 int wifi_get_module_status (char *ctl_fp); 109 110 111 static int insmod(const char *filename, const char *args) 112 {





206 int wifi_load_driver() 207 { 208 #ifdef WIFI_DRIVER_MODULE_PATH 209 char driver_status[PROPERTY_VALUE_MAX]; 210 int count = 100; /* wait at most 20 seconds for completion */ 211 212 if (is_wifi_driver_loaded()) { 213 return 0; 214 } 215 216 // Wifi power control & wakeup enable 217 wifi_set_module_status(WIFI_WAKEUP_CTL_FP, 1); usleep(10000); 218 wifi_set_module_status(WIFI_REG_CTL_FP, 1); usleep(10000); 219 wifi_set_module_status(WIFI_RESET_CTL_FP, 1); sleep(1); sync(); 220 221 222 if (insmod(DRIVER_MODULE_PATH, DRIVER_MODULE_ARG) < 0) { 223 LOGE("insmod(DRIVER_MODULE_PATH = %s, DRIVER_MODULE_ARG = %s) FAIL!!!", DRIVER_MODULE_PATH, DRIVER_MODULE_ARG); 224 wifi_set_module_status(WIFI_WAKEUP_CTL_FP, 0); usleep(10000); 225 wifi_set_module_status(WIFI_REG_CTL_FP, 0); usleep(10000); 226 wifi_set_module_status(WIFI_RESET_CTL_FP, 0); sleep(1); sync(); 227 return -1; 228 } 229 230 if (strcmp(FIRMWARE_LOADER,"") == 0) {




259 int wifi_unload_driver() 260 { 261 usleep(200000); /* allow to finish interface down */ 262 #ifdef WIFI_DRIVER_MODULE_PATH 263 if (rmmod(DRIVER_MODULE_NAME) == 0) { 264 int count = 20; /* wait at most 10 seconds for completion */ 265 while (count-- > 0) { 266 if (!is_wifi_driver_loaded()) 267 break; 268 usleep(500000); 269 } 270 271 wifi_set_module_status(WIFI_WAKEUP_CTL_FP, 0); usleep(10000); 272 wifi_set_module_status(WIFI_REG_CTL_FP, 0); usleep(10000); 273 wifi_set_module_status(WIFI_RESET_CTL_FP, 0); sleep(1); sync(); 274 275 276 usleep(500000); /* allow card removal */ 277 if (count) { 278 return 0;


int wifi_set_module_status(char *ctl_fp, unsigned char status) { int fd, ret, nwr; char buf[10]; if((fd = open(ctl_fp, O_RDWR)) < 0) { LOGE("%s(%s) : Cannot access \"%s\"", __FILE__, __FUNCTION__, ctl_fp); return -1; // fd open fail } memset((void *)buf, 0x00, sizeof(buf)); if(status) nwr = sprintf(buf, "%d\n", 1); else nwr = sprintf(buf, "%d\n", 0); ret = write(fd, buf, nwr); close(fd); if(ret == nwr) { LOGI("%s : write success (on = %d)", ctl_fp, status); return 0; } else { LOGE("%s : write fail (on = %d)", ctl_fp, status); return -1; } } //---------------------------------------------------------------------------------------------------------------- int wifi_get_module_status(char *ctl_fp) { int fd, ret, nrd; char buf[10]; if((fd = open(ctl_fp, O_RDONLY)) < 0) { LOGE("%s(%s) : Cannot access \"%s\"", __FILE__, __FUNCTION__, ctl_fp); return -1; // fd open fail } memset((void *)buf, 0x00, sizeof(buf)); nrd = read(fd, buf, sizeof(buf)); close(fd); // read ok if(nrd) { if(!strncmp(buf, "1", 1)) { LOGI("%s : status == 1", ctl_fp); return 1; // wakeup } else { LOGI("%s : status == 0", ctl_fp); return 0; // suspend } } LOGI("%s(%s) : module status == unknown", __FILE__, __FUNCTION__); return -1; } //---------------------------------------------------------------------------------------------------------------- int wifi_module_wakeup_status() { int fd, ret, nrd; char buf[10]; if((fd = open(WIFI_WAKEUP_CTL_FP, O_RDONLY)) < 0) { LOGE("%s(%s) : Cannot access \"%s\"", __FILE__, __FUNCTION__, WIFI_WAKEUP_CTL_FP); return -1; // fd open fail } memset((void *)buf, 0x00, sizeof(buf)); nrd = read(fd, buf, sizeof(buf)); close(fd); // read ok if(nrd) { if(!strncmp(buf, "1", 1)) { LOGI("%s(%s) : module status == wakeup", __FILE__, __FUNCTION__); return 1; // wakeup } else { LOGI("%s(%s) : module status == suspend", __FILE__, __FUNCTION__); return 0; // suspend } } LOGI("%s(%s) : module status == unknown", __FILE__, __FUNCTION__); return -1; } //---------------------------------------------------------------------------------------------------------------- int wifi_module_wait_time(int waitTime) { LOGI("%s(%s) : module wait time = %d sec", __FILE__, __FUNCTION__, waitTime); sleep(waitTime); sync(); return 0; }



위와 같이 수정 하고 libhardware_legacy.so를 넣습니다.

bcm4329.ko는 kernel에서 make modules로 만들어 넣습니다.










market 사용




gapps는 아래 파일에서 받았습니다.

위에 system을 adb push로 밀어 넣으면 몇개 중복되는 apk가 존재하여 문제가 발생합니다.

그래서 중복되는 apk를 삭제하여 묶었습니다.

http://dl.dropbox.com/u/4485660/gapps-ics-20111122-full-blade_codewalker.tar.gz



android-4.0.3_r1(IML74k) 올려 봤습니다.


gps

odroid-7 gingerbread의 gps library를 드대로 사용하니 gps도 동작하네요.
int.rc에 gps 노드만 바꾸면 됩니다.

 29     chown gps root /sys/class/sec/gps/GPS_PWR_EN/value
 30     chmod 660 /sys/class/sec/gps/GPS_PWR_EN/value
 31                                                   
 32     #===================================================================
 33     #                                         
 34     # Odroid GPS Device name Setting                         
 35     #                                                       
 36     #===================================================================
 37     setprop ro.kernel.android.gps s3c2410_serial1            
 38     chmod 0666  /dev/s3c2410_serial1
 39                    
 40            
 41 on fs                
 42     mkdir /efs 0775 radio radio




가속 센서 역시 odroid7의 orientationd, geomagneticd, sensors.odroid7.so를 그대로 사용하니 동작 합니다.

지자기 센서는 역시 동작하지 않네요.









앞에서 추가적으로 수정된 내용은 ICS.tar.gz에 계속 반영 됩니다.

2011년 11월 21일 월요일

ZigBee VS. BLE(Bluetooth 4.0)

2011/11/18에 COEX에서 하는 RFID/USN Korea 2011을 참관하였습니다.

RFID는 들어 봤지만 USN은 뭔지도 모르고 갔는데 ubiquitous sensor network 이더군요.


RFID야 매우 오래된 분야이고 물류쪽에 적용하여 많이 활성화된 기술입니다.




아래 사진은 RFID를 통해서 물류쪽에 적용할 수 있는지 시물레이션하는 모형인데 모형이 참 인상적이 었습니다. 




모형 제작에 상당한 시간과 돈이 들었을 것 같은데 마치 박물관이나 전시회에서나 볼 정도의 완성도였습니다.


이제는 Nexus S, Galaxy S2에 NFC가 기본 탑재되어 있어서 산업/물류 뿐만 아니라 실생활에 어떻게 활용 될지에 대한 내용이 흥미로 왔습니다.


쿠폰을 문자로 받고 화면에 바코드나 번호를 보여 주는 방식에서 NFC를 통해 쿠폰을 받고 결재하는 방식으로 NFC를 이용함으로써 직관적이라는 느낌이 들었습니다. 


CGV에서 쿠폰 및 결재를 NFC가 있는 핸드폰에서 곧 서비스 계획에 있으며 데모를 시현하고 있었습니다.


그리고 기존에 NFC가 없는 핸드폰이나 특수 사용을 목적으로 NFC 외부 모듈 형식에 제품도 많이 보였습니다.




주류 마개에 RFID tag를 넣고 RFID 리더기로 읽고 Bluetooth과 연결된 핸드폰으로 tag 값을 전달 후 인터넷을 통해 진품확인하는 시스템입니다.


그리고 저의 관심 분야인 USN입니다.


아래 사진은 휴인스에서 USN 개발킷입니다.
http://www.huins.com/m16.php?m=rd&no=77#bimg




안드로이드 단말기에서 현관문도 열 수 있고 전구도 on/off가 가능합니다.


여기에 사용된 방식이 ZigBee입니다.


BLE(Bluetooth 4.0)과 ZigBee 어느 쪽이 USN에서 승자가 될까요?


둘다 저전력을 목표로 제작된 것입니다.


하지만 iPhone 4S에 BLE가 적용된 칩이 들어갔고 차후 안드로이드 역시 BLE가 적용된 Wi-Fi/Bluetooth 가 적용된 칩이 적용되겠죠.
broadcom의 bcm4330이 나와 있습니다.


BLE가 전망이 더 밝은 이유가 안드로이 Open Accessory Development Kit에서 채용되지 않을까 예상해 봅니다.


현재 adk는 USB 통신인데 이로 인해 말이 안되는 accessory가 되었죠. 
Google에서 다음 버전은 Bluetooth 무선 accessory가 될것이라 했기 때문에 BLE가 ZigBee 보다는 더 전망이 밝다고 보입니다.



2011년 11월 18일 금요일

foursquare를 이용한 Googl Calendar 관리

Google Calendar를 이용하여 일정관리를 많이 하실겁니다.

스마트폰으로 calendar 어플을 띄워서 시간 장소를 입력하기가 막상 귀찮아서 몇번 하다가 말죠.

foursquare를 이용하여 google calendar에 일정관리 하는 간단한 방법이 있습니다.

일단 스마트폰에서 foursquare를 이용하여 check-ins을 하시고

자신의 foursquare 계정에서 아래의 주소를 들어가시게 되면 URL 주소를 확인 하실 수 있습니다.

https://ko.foursquare.com/feeds/

그리고 Google Calendar에서 다른 캘린더 -> URL 추가에 위에서 ics 링크를 넣어주면 foursquare에서 check-in한 장소들이 Google Calendar에 추가됩니다.