2014년 11월 3일 월요일

Meteor 1.0 - Android/iOS 앱을 만들기 위해 Cordova plugin을 사용해보자

Camera와 Gallery를 사용하는 앱을 Meteor로 만들자.

준비
meteor 설치 (https://www.meteor.com/install)

실행과정 :

project를 생성하고
$ meteor create camera-practice
$ cd camera-practice

iOS, android 환경을 추가한다.

$ meteor add-platform ios
$ meteor add-platform android

You must agree to the terms to proceed.       
Do you agree (Y/n)? 
에서 Y혹은 enter
android: added platform 

플랫폼 추가 완료.

플러그인 추가
meteor add cordova:org.apache.cordova.camera
Must declare exact version of dependency: org.apache.cordova.camera@undefined

에서 버전 정보를 확인해보니 0.3.4-dev 하지만 역시 빌드시 오류가 있으므로 안전한 0.3.2로 가자.

$ meteor add cordova:org.apache.cordova.camera@0.3.2
added cordova plugin org.apache.cordova.camera@0.3.2

성공. cordova라는 namespace만 붙여주면 마치 원래 Meteor package인양 가져오는 모습이 아주 흐뭇하다 :)

나는 coffeescript를 좋아하니까

meteor add cofffeescript

일단 필요없는 초기파일 html, css, js들은 다 지우고
client 디렉토리를 하나 만든 후 html과 coffee 파일을 만들자
rm *
mkdir client
cd client
touch getPicture.html
touch getPicture.coffee

getPicture.html
<head>
  <title>cordova-meteor-practice-camera</title>
  <meta name="viewport" content="width=device-width">
</head>
<body>
  <h1>Camera Demo</h1>
  {{> getPicture}}
</body>

<template name="getPicture">
  <button id="album">from Album</button>
  {{#if photo}}
  <div>
    <img src="{{photo}}">
  </div>
  {{/if}}
</template>

getPicture.coffee
Template.getPicture.helpers
  photo: ->
    Session.get 'photo'
Template.getPicture.events
  'click #album': ->
    navigator.camera.getPicture (data)->
      Session.set 'photo', "data:image/jpeg;base64,#{data}"
    ,
      (error)->
        new Meteor.Error "cordovaError", error
    ,
      destinationType: Camera.DestinationType.DATA_URL
      sourceType: Camera.PictureSourceType.PHOTOLIBRARY

coffee 내용을 잘 모르겠다면 http://js2coffee.org 에서 복붙하여 변환해보자.
노파심에 말하지만 오른쪽에 붙여야한다 :)

getPicture template에서 album이라는 id를 가진 button을 click했을 때 event를 받아
navigator.camera.getPicture 를 실행하여 사진엘범의 사진을 가져와 DATA_URL형태로 받은 것을 photo라는 Session 값으로 넘겨준다.
그러면 Reactive 객체인 photo는 같은 이름의 helper인 photo로 img에 들어가는 구조이다.

$ meteor run ios
   Installing Cordova plugins...             [=============             ] 50% 31.1s

플러긴 한참 설치하고 빌드하고 처음 시작을 준비한다.

=> Started proxy.                             
=> Started MongoDB.                           
=> Started app on iOS Simulator.              
=> Started your app.                          

=> App running at: http://localhost:3000/

이렇게 나오고 ios simulator를 확인해본다.
디버깅을 하려면 Develop > iOS Simulator > meteor.local 을 선택해보면 된다.

console에서 device나 cordova, navigator, Camera 객체 등등의 내용을 확인해보면 흥미로울 것이다.

iOS Simulator에서 이쁜 기본 Meteor splash screen과 함께 앱이 실행된다.
Simulator라 내장 카메라 작동이 안되므로 Album을 구현하였다.
화면이 나오면
버튼을 눌러보자.
사진을 열람하게 할거냐고 권한을 물어본 뒤 사진을 선택할 수 있다.
 선택하면 버튼 하단에 사진이 나오는 것을 확인할 수 있다.
camera plugin에 대한 자세한 내용은 https://github.com/apache/cordova-plugin-camera/blob/master/doc/index.md 를 참조하자.

폰을 연결하고 meteor run ios-device 로 실행하면 카메라도 테스트해볼 수 있다.

  <button id="camera">from camera</button>
버튼을 하나 더 만들고

Template.getPicture.events 아래에
  'click #camera': ->
    navigator.camera.getPicture (data)->
      Session.set 'photo', "data:image/jpeg;base64,#{data}"
    ,
      (error)->
        new Meteor.Error "cordovaError", error
    ,
      destinationType: Camera.DestinationType.DATA_URL
      sourceType: Camera.PictureSourceType.CAMERA

이 부분을 추가해보자.
사실 sourceType은 default가 CAMERA이므로 생략해도 무방하다.
놀라운 점이 하나 있다면 다시 앱을 재실행하지 않아도 부드럽게 적용이 된다.
이것은 반복적인 UI 확인/테스트를 요하는 모바일 앱 작성에 있어 강력한 장점이다.


개인적인 감상으론 Hot Code Push를 비롯하여 깔끔한 파일구조등등을 고려했을때 그냥 서버없는 cordova app을 만든다고 해도 Meteor를 추천하고 싶은 심정이다.

게다가 coffeescript 를 쓰기 위해 멍청한 javascript task runner류들을 만들지 않아도 되는 것이 너무 좋다.
grunt? gulp? jake? 잊어라. 그리고 Meteor를 하자.

2014년 10월 31일 금요일

Meteor 1.0 - LocalMarket example - Direcctory 구조 분석

드디어 Meteor가 1.0을 찍었다. 감동 ;ㅅ;)/

Todo가 예쁘게 바뀐 건 봤고 새로운 예제 앱이 생겼다.
그 이름은 바로 LocalMarket.

동영상을 찍어서 보여주고 싶지만 귀찮기도 하고 어짜피 meteor create --example localmarket 치면 다 알테니까.

이전까지 실험적이었던 Mobile 정확히 말해 Cordova 와의 통합이 아주 멋지게 이루어졌다.
실행 옵션이 좀 많아졌는데

meteor run
: 그냥 Meteor 웹서버만 기동. 이하 아래의 것들도 기본적으로 Meteor 서버를 실행한다.

meteor run android
meteor run ios
: 안드로이드, iOS 시뮬레이션을 실행한다. 안드로이드의 경우 Hardware Accelerated Execution Manager (Intel HAXM) 을 설치한다.

meteor run android-device
meteor run ios-device
: 실제 iOS/Android 장비에서 실행한다.

실행에 대해선 어짜피 해보면 되니까 여기쯤 해두고
Web과 Mobile(android/iOS)간의 차이를 어떻게 극복했는지가 궁금한 거니까 디렉토리 구조를 살펴보기로 하자.


먼저 디렉토리 구조를 보자.
client 는 사용자가 실제로 보는 html+css+js+기타등등이고
server 는 backend 쪽인 것까지는 기존과 동일하다.
lib는 client/server 양쪽에서 실행되는 Collection, Router등등의 코드가 있다.

client 쪽에선 lib 아래에 jquery.touchwipe.js 를 쓴게 보인다.
그리고 head.html을 따로 분리하여 공통 헤더를 만들어 놓았고
init.js 에선 사용자가 앱/웹을 실행시 Geolocation.currentLocation(); 를 사용하여 위치정보를 수집할 수 있도록 해놓았다.
package 는 atmosphere가 아닌 프로젝트별 custom package를 넣어놓은 것을 확인할 수 있다.
mrt 시스템과 통합하면서 용도가 바뀐 부분이다.

public 은 font/icon/image/favicon/apple-touch-icon 과 같은 정적 이미지와 파일들을 관리하고 있다.

여기까지는 기존에 있거나 있었는데 조금 변경이 있었던 부분들이고
1.0이 되면서 새로 생긴 디렉토리와 파일들이 있다.

resource 는 기기 해상도별 아이콘과 초기 시작화면인 splash 이미지들을 모아놓은 곳이다.
HAXE처럼 SVG를 지원하면 해상도 별로 저렇게 만들지 않아도 될텐데라는 생각이 들긴 하지만 제법 깔끔하게 관리하고 있다는 인상이다.

cordova-build-override 의 경우 무릎을 탁 쳤는데 iOS *-info.plist의 경우 그냥 cordova에서 관리하기 좀 불편한 파일이라 짜증났었는데 이렇게 분리해줘서 너무 좋았다.
가령 상태바를 숨긴다던가 오리엔테이션을 지정한다던가 등등의 설정값은 여기에서 지정하면 된다.

mobile-config.js 는 앱을 만들때 꼭 확인해야하는데 어떤 아이콘을 쓸지 시작 화면은 뭘 할지 등등을 여기에 지정하면 된다.

이외에도 .meteor 디렉토리를 보면 몇가지 변경점을 발견할 수 있는데
.id 파일이 있어 유니크 키를 저장하고 있고고
platforms파일엔
server
browser
ios
android
이런 내용들이 있다.
iOS, android야 그렇다치고 'server나 browser중 하나만 할 수도 있나?' 하는 엉뚱한 생각이 들기도 하다.
release엔 현재 프로젝트의 Meteor 버전이 있고
versions엔 사용하고 있는 package들의 버전이 있다.

packages를 보면 재밌는 것들이 몇몇 보이는데

jquery-waypoints - 무한 스크롤 및 스크롤 고정등 스크롤 관련 유용한 패키지
fastclick - 모바일에서 클릭 지연시간을 없애주는 패키지
tmeasday:publish-counts@0.3.1 - publish 시점에 collection의 갯수를 카운트하는 패키지
percolate:velocityjs - velocity 테스팅 패키지가 아니라 animation 관련 패키지
mdg:camera - webkit브라우저 공통 카메라 패키지
mdg:geolocation - webkit브라우저 공통 위치 패키지

정도 눈여겨 볼만하다.
아직도 갈길은 멀지만 이정도 훌륭한 결과물을 이끌어낸 percolate studio에 박수를 보낸다.

2014년 10월 12일 일요일

Ubuntu 12.04 - RDP에서만 mount 권한이 없을때

Unable to mount USB, Not Authorized 오류가 날때가 있다.

직접 콘솔에서 들어가면 잘 되는데 RDP로 접근할 경우 해당 계정에 권한 문제가 있을 수 있다.

http://ubuntuforums.org/showthread.php?t=1336847&page=7 에서 찾았다.

sudo vi /usr/share/polkit-1/actions/org.freedesktop.udisks.policy

해서 보면

<allowed_any>no</allowed_any>

라는 부분이 있다

이부분을

<allowed_any>yes</allowed_any>

로 바꾸고 재부팅하자.

알아서 마운트까지 잘 된다.

2014년 9월 29일 월요일

Arduino+Bluetooth 연결 후 터미널에서 테스트하기

Arduino를 보고 있다.

Bluetooth 모듈하고 연결은 tx,rx를 서로 교차연결하고 전원만 받아주면 만사 오케이더라.


이렇게 해서


이렇게 하긴 했는데

테스트 하기 위해선 nc 같은 터미널로 하면 쓸 수 없을까 싶었는데
그냥 screen 명령을 쓰면 되더라.
Bluetooth Pairing 후

$ ls /dev/tty.*
/dev/tty.Bluetooth-Incoming-Port /dev/tty.HC-06-DevB
/dev/tty.Bluetooth-Modem

해보니 테스트 용으로 쓰고 있는 HC-06-DevB가 보이더라.

$ screen /dev/tty.HC-06-DevB 
으로 접근하면 시리얼 터미널로 돌입한다.
에코가 있으면 에코를 쏠테고 아니면 그냥 받아준다.
뒤에 전송속도를 써서

$ screen /dev/tty.HC-06-DevB 9600

이렇게 접근도 가능하다.
커맨드를 치고 enter를 치면 텍스트를 전달한다.

테스트를 마치고 나갈땐 ctrl+a, ctrl+\ 를 입력하면 

Really quit and kill all your windows [y/n]
하고 물어본다.
y를 눌러서 나가면 된다.

2014년 8월 3일 일요일

Meteor에서 웹서버 설정 - nginx

http://www.andrehonsberg.com/article/install-nginx-141-meteor-js-websocket-ubuntu-1204

3000->80포트 포워딩하느라 nginx를 사용하긴 했는데 (그리고 ssl도 해야하고 등등)
맘에 걸리는 점이 두가지 있었다.


  1. gzip을 안써도 되나
  2. 정적 resource를 meteor가 다루지 않도록 해야
딱 내가 찾던거네!

근데, meteor에선 css의 경우 경로가 /fc376dc60222227945af14b78724770fb1dbb699.css?meteor_css_resource=true 이런 식으로 뒤에 ?meteor_css_resource=true 가 붙는다.

정규식만 조금 고쳐주자.


location ~* "^/[a-z0-9]{40}\.(css|js)$" {

이 부분을 css 뒤에 개행이 아닌 아무거나 와도 되도록 .*를 추가해주자. 

location ~* "^/[a-z0-9]{40}\.(css.*|js)$" {

어 이거 하고 나니 PageSpeed Insights 가 100점이 되넹?

2014년 7월 28일 월요일

오늘의 닭짓일기 - iOS iOS iOS... plugins

자 이제 더러운 짓을 할 때다.
각종 권한들 왕창
플러그인들도 왕창
미리 설치해놓고 잠수함 패치로 앱스토어를 거치지 않고 업데이트할 수 있도록 미리 준비하는 것이다.

TestFlight에 올리록 Archive를 하니
'Cordova/CDVViewController.h' file not found
오류가 계속 나서 stackoverflow를 전전하다 보니
아뿔싸 내 Cordova 버전이 너무 낮다. 3.5로 다시 업글
npm install -g cordova

그리고 iOS 7에선 Status bar가 내용을 가린다.
MainViewController.m을 좀 수정하자.

- (void)viewWillAppear:(BOOL)animated
{
    // View defaults to full size.  If you want to customize the view's size, or its subviews (e.g. webView),
    // you can do so here.
    //Lower screen 20px on ios 7
    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) {
        if(self.webView.frame.origin.y == 0) {
            CGRect viewBounds = [self.webView bounds];
            viewBounds.origin.y = 20;
            viewBounds.size.height = viewBounds.size.height - 20;
            self.webView.frame = viewBounds;
        }
    }

    [super viewWillAppear:animated];
}

icons도 복사하고
Icon.png
Icon@2x.png
Icon-72.png
Icon-72@2x.png
Icon-Small.png
Icon-Small@2x.png
얘는 왜 자동으로 안넣는거야 귀찮게.

splash는 다 시커멓게(혹은 하얗게) 바꾸자

Default@2x~iphone.png
Default-568h@2x~iphone.png
Default-Landscape@2x~ipad.png
Default-Landscape~ipad.png
Default-Portrait@2x~ipad.png
Default-Portrait~ipad.png
Default~iphone.png

그리고 URL Scheme 지원해야하니까

<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>scheme명</string>
</array>
</dict>
</array>
*-info.plist에 추가하자. 

으아 하루종일 삽질했네.
<preference name="webviewbounce" valvue="true"/>
어디서 자꾸 죽나했더니 value에 v 들어가서 죽는거였군;
오타 한번에 하루를 통째로 날렸다. 이러니 아무리 뒤져도 안나오지.
역시 맞춤법 검사기는 소중한거여.

com.urbanairship.phonegap.PushNotification 은 세련되보였지만 서비스 종속이 있어 제거
org.apache.cordova.splashscreen 도 제거. 스플래시 스크린따위는 쓰지 않는다.

adhoc을 위해 사용자를 추가하고 있는데
역시 그냥 사용자한테 UDID를 불러달라고 하면 안되겠다.
먼저 https://developer.apple.com/account/ios/certificate/certificateList.action 에서
Certificates 에서 iOS Development, iOS Distribution 만들고 APNS 도 Dev, Dist 만들자.
Identifiers 에서 App Id도 만들고
Devices 에서 장비추가할 때 먼저 testflight로 초대장을 보내놓고
https://www.testflightapp.com/dashboard/team/all/ 같은 곧에서 추가할 사용자를 선택하여 오른쪽 Actions를 눌러서 Export iOS Devices눌러서 txt파일을 다운받고
다운 받은 파일을 https://developer.apple.com/account/ios/device/deviceCreate.action 에서 Register Multiple Devices 를 통해 일괄 등록하자.

여기서부터 좀 빡치는 점인데 매번 유저 하나 등록할 때마다 "~/Library/MobileDevice/Provisioning Profiles" 경로에서 뒤져서 기존 것을 삭제하고 mobileprovision을 등록해야한다.
그렇지 않으면

이 꼴이 난다.
물론 맨 위엣것이 옛날 것.
미치미치.
파일 이름은 또 어찌나 아름다우신지.
0C44F8C6-65F7-46BD-BEDC-E6FA6CA6577B.mobileprovision
373936C6-AC92-48A9-B73B-418F1E666EF2.mobileprovision
490E1B9A-FCC5-4800-9B5D-3EE811A9E50C.mobileprovision
55D3B3F7-8768-4859-99E4-4C5E5045C253.mobileprovision
5C0B6FAF-A807-4BFD-A5CB-5CE5C4AA3F30.mobileprovision
8EFBC62E-21F0-46A7-B215-105C29475C7E.mobileprovision
984351B5-C42F-496B-9203-CE1FB153C371.mobileprovision
B278CC8C-C2B6-42A9-B0EA-B6D30FFEFD8F.mobileprovision
C7D59812-A742-48EC-855D-BCBDF9F9884C.mobileprovision

이런다.
날짜순으로 보고 지웠는데


안되쟎아! 엉뚱한 게 날아가쟎아!


결국, 눈물 머금고 다시.
잘 보니 XCode 에서 Preference > Accounts > View Details 에서도 볼 수 있단 걸 알았지만 결국 지울 수 없어서 아무 도움 안됨.
http://stackoverflow.com/a/18923552/880991
stackoverflow가 없었으면 영원히 못지웠겠지.

암튼 유저 추가시 시나리오는

  1. testflight로 UDID 수집
  2. testflight에서 export
  3. export한 txt 파일을 https://developer.apple.com/account/ios/device/deviceCreate.action 에서 등록
  4. 기존 mobileprovision을 "~/Library/MobileDevice/Provisioning Profiles"에서 삭제
  5. https://developer.apple.com/account/ios/profile/profileList.action?type=production 에서 adhoc mobileprovision을 생성, 혹은 수정하여 신규 장비 추가(수정시 체크박스 체크)
  6. adhoc mobileprovision 생성 후 다운로드 및 더블 클릭
  7. XCode에서 Preference > Accounts > View Details 에서 리프래쉬하여 확인
  8. 프로젝트 Archieve
  9. 재업로드 및 메일 공지
이정도 되겠다.
이 삽을 뜨다가 정신을 차려보니 iOS계정이 만료되어있군.
천천히 하자.



2014년 7월 26일 토요일

오늘의 닭짓일기 - Amazon EC2 + Meteor

wwwizer 적용이 생각보다 오래걸리더라.
아무튼 지금은 잘됨.
RalphChat 이 오픈소스가 되어 기쁨. 적절한 타이밍.
AWS는 신청하니 별거 없는데
Security-Group 에서
Type
Protocol
Port Range
Source
SSH
TCP
22
0.0.0.0/0
HTTP
TCP
80
0.0.0.0/0
이렇게 잡아주고
nginx 설치 후 포트포워딩 등등을 함
http://www.andrehonsberg.com/article/install-nginx-141-meteor-js-websocket-ubuntu-1204
이거 보고 했는데 내 경우엔 apt-get 으로 설치하고보니 include sites-enabled/*; 부분은 필요 없었고 sites-available 에 설정파일 만들고 sites-enabled에 심볼릭 링크 만드는 게 전부였다.

그리고 DB는 따로 분리했는데 MongoHQ로 지정하였음.
어드민 겸 잘됐지뭐. 속도는 meteor.com 호스팅 보단 빠르지 않나 싶음.
google analytics의 웹페이지 속성도 변경하고
안드로이드 버전업도 함. 벌써 0.0.7
도메인 문제가 전부 해결되었으니 다른 호스팅을 써도 이젠 의존성이 없음.

pm2 를 써서 디플로이 하도록 했는데 watch 옵션을 쓰면 "거의" 무정지 운영도 가능할 듯.

2014년 7월 25일 금요일

오늘의 닭짓일기 - Cordova + Meteor


  1. app에 meteor-rider 적용
  2. 기존 url scheme 관련 plugin인 com.borismus.webintent을 지웠다가 재설치
  3. iOS 적용. 정상작동 확인
  4. talk 섭 도메인 생성 및 meteor deploy새로 완료
  5. wwwizer 에 naked domain 신청함. 아직은 안됨.
  6. 마이그 완료
새 도메인으로 앱 업뎃도 해야겠군.
언제든지 호스팅을 바꿔도 되도록.

meteor-rider는 hijacking DOM을 이용해 로컬에서 먼저 기동하고 호스팅하고 있는 원격지 앱으로 갈아타기 하는 아주 간단한 방식인데 단점은 http://zeroasterisk.com/2013/08/22/meteor-phonegapcordova-roundup-fall-2013/ 몇몇 하드웨어 관련 플러그인이 작동하지 않을 수도 있다고 한다.
그런데 RalphChat이 쓴걸 보니 별 문제는 없어보인다. Push 같은 게 작동하지 않으려나?

iOS 적용은 초기에 네트웍 연결 불가능한 상태에서 404메시지 같은 걸 뿌릴 때 심사팀에서 매우 안좋아하더라. 거의 리젝이라고 보면 된다.

https://github.com/apache/cordova-ios/blob/master/guides/Cordova%20Custom%20URL%20Scheme%20Handling.md

iOS의 경우 URL Scheme을 적용하는 건 Android보다 간단. 원래 내부적으로 지원하나보다.
단 android의 경우는 meteor app에서 사용한 반면 iOS는 최초 index.html로 진입할때 하도록 함.
뭐 상관없나 싶기도 하지만.



2014년 5월 1일 목요일

3D가속을 지원하는 Ubuntu 12.04LTS 를 Multiboot RK3188 설치 후 설정

https://plus.google.com/+IanMORRISON 님에게 감사의 말씀을 일단

1. SD 준비하기
먼저 용량 넉넉한 MicroSD를 FAT32로 포멧한 후
MiniTool Partition Wizard 같은 걸로 Ext4 파티션을 만들어준다.

2. 듀얼부팅용 Flash하기
RKAndroidTool.exe 를 일단 받자
순서대로 올려보는데 일단 기본적으로 USB Driver 등은 설치+적용해놓고 리커버리모드로 부트.

update.img는
https://drive.google.com/file/d/0B99O3A0dDe67NjVLSHlhQXVnX0k 받아서
v1.7에서 올려서 upgrade했다. 파일이름이 아마 rikomagic-linuxium-bootloader 인데 내용 물은 update.img임.
이걸로 듀얼부팅은 끝.

(최신 kitkat 적용 radxa 롬이 있긴 하지만 안정화도 그렇고 멀티부팅도 아직이라 보류http://radxa.com/2014/03/25/android-4-4-2-preview-firmware-released/ )

하지만 몇가지 패치는 해주자
v1.37에서 boot(5번째)에
https://drive.google.com/file/d/0B99O3A0dDe67NjVLSHlhQXVnX0k
minix-linuxium-updated-boot.img
요거 한번 올리고 run

rikomagic-linuxium-updated-kernel.img
요거 한번 올리고 run

3. 이미지를 올릴 차례다.
https://docs.google.com/file/d/0B99O3A0dDe67S1hQQ2VybldVYU0/edit 를 sd카드에 올리고
부트한 뒤 c 를 선택 커맨드라인 모드로 돌입. 쭉쭉 입력해주자.
mke2fs /dev/mmcblk0p1 <enter>
mount /dev/mmcblk0p1 /mnt/sdcard <enter>
mount /dev/mtdblock9 /mnt/nand <enter>
cd /mnt/nand/Download <enter>

mount -o loop linuxium-ubuntu1204-desktop-rfs.img /mnt/misc <enter>
cd /mnt/misc <enter>
for i in * <enter>
do <enter>
echo copying $i  <enter>
cp -a $i /mnt/sdcard <enter>
echo copied <enter>
done <enter>

올리는 이미지가 mali 그래픽 칩셋에서 3D지원을 하는 놈인데
최초 우분투 부팅 (암호는 p) 후
sudo su -
한 뒤 root로

rm -rf /usr/lib/arm-linux-gnueabihf/mesa-egl
해주고 
sudo chmod 666 /dev/dri/card0
sudo chmod 777 /dev/mali
요렇게 하라는데 내 경우엔 /dev/dri/ 경로 자체가 없었다.

아래 달린 댓글에 보면
mali_drm.ko이 자동으로 로드되지 않는 경우가 있다고 하는데
cd /lib/modules/3.0.36+; sudo insmod mali_drm.ko
실행한 후 디스플레이 매니저를 재시작한다.
sudo restart lightdm
화면이 껌뻑하고 다시 로그인
/dev/dri/card0 경로가 생겼다!

sudo chmod 666 /dev/dri/card0
sudo chmod 777 /dev/mali

권한을 주고
테스트 해보자.

es2gears
glmark2-es2
둘다 잘 돌아가면 성공.

Wifi 설정하고

Locale 설정도 하자.
export LANGUAGE=en_US.UTF-8
export LANG=en_US.UTF-8
export LC_ALL=en_US.UTF-8
locale-gen en_US.UTF-8
sudo locale-gen en_US.UTF-8
sudo dpkg-reconfigure locales

개발관련 의존성 설치
sudo apt-get update

sudo apt-get install build-essential openssl libssl-dev pkg-config git-core scons libpcre++-dev libboost-dev libboost-program-options-dev libboost-thread-dev libboost-filesystem-dev curl

java 설치
sudo apt-add-repository ppa:webupd8team/java
sudo apt-get update
sudo apt-get install oracle-java7-installer
정도로 일단 마무리.

만일 1080p가 아닌 720p 디스플레이를 쓴다면 화면이 잘릴 수 있다.
sudo echo 1280x720p-60 > /sys/class/display/display0.HDMI/mode
해상도를 변환해주면 편리하다.

* resize partition POWERTIP!
http://www.hagensieker.com/styled-26/index.html 감사합니다.

root@LINUXIUMONE:/home/linuxium# df
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/mmcblk0 2580272 1809192 640008 74% /
udev 955244 4 955240 1% /dev
tmpfs 382900 576 382324 1% /run
none 5120 0 5120 0% /run/lock
none 957248 264 956984 1% /run/shm
root@LINUXIUMONE:/home/linuxium# resize2fs /dev/mmcblk0 
resize2fs 1.42 (29-Nov-2011)
Filesystem at /dev/mmcblk0 is mounted on /; on-line resizing required
old_desc_blocks = 1, new_desc_blocks = 2
Performing an on-line resize of /dev/mmcblk0 to 7728896 (4k) blocks.
The filesystem on /dev/mmcblk0 is now 7728896 blocks long.

root@LINUXIUMONE:/home/linuxium# df
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/mmcblk0 30430236 1812332 27072472 7% /
udev 955244 4 955240 1% /dev
tmpfs 382900 576 382324 1% /run
none 5120 0 5120 0% /run/lock
none 957248 264 956984 1% /run/shm
------------------------------

df로 현재 사용하고 있는 block명을 확인하고
resize2fs <block경로>
하고 나면 Use%가 줄어든, 그러니까 용량이 늘어난 것을 확인할 수 있다.
2.5GB의 적은 용량에 실망할 필요가 없다.


+추가
지역이 다를 경우 시간이 안맞을 수 있는데 root 권한으로

cp /usr/share/zoneinfo/Asia/Seoul /etc/localtime

해주면 Asia/Seoul 기준으로 된다.

2014년 3월 10일 월요일

Meteor/handlebars에서 radio/select 다루기

자주쓰지만 은근 귀찮은 것이 radio와 select다.
특히 최초에 렌더링 할때 선택하게 하는게 번거롭다.
#each로 option이나 input에 들어갈 별도의 키를 find의 transform에서 만들거나 아예 fetch를 하거나 array를 조작하거나 하는 건 어렵지 않지만 매번 같은 상황일때마다 코딩을 해야되니까 안 이쁘쟈나. (그렇쟈나 손구락 뿌러지쟈나 카피엔 페이스트 귀찮쟈나 짜증나쟈나!)

물론 checkbox도 귀찮지만 비슷하게 응용하면 될 것이니
handlebars의 block helpers를 사용하여 이 귀찮음을 해결해볼 수 없을까 해서 코드를 만들어보았다.

먼저 select를 해보면 다음과 같은 그림인데

<select>
  {{#each array}}
  <option value="{{code}}">{{name}}</option>
  {{/each}}
</select>

array중 code가 특정값과 일치하면 selected="selected"가 되도록하려면 간단하게는 option이라는 Helper를 만들어 {{option name code value}}식으로 할 수도 있겠지만
<option> 이라는 객체가 없어지니까 별로 좋지 않다.
그렇다면 특정 블록을 감싸안아서 인자로 받은 값과 같은 option이 있는지 찾아서 수정한 후 대치하면 될 것이다라고 생각.

Handlebars.registerHelper "select", (value, options) ->
select = document.createElement("div")
$(select).html options()
$("option", select).filter("[value='#{value}']").attr "selected", "selected"
select.innerHTML
이런 식으로 구현해보았다.
registerHelper는 마지막 인자 뒤에 옵션이 붙을 경우 해당 템플릿을 렌더링하는 함수를 가르킨다.
options()로 select block helpers 안의 html을 가져온 뒤 DOM을 생성하고
filter로 값을 찾은 후 attr로 조작해보았다.

<select>
  {{#select matchValue}}
  {{#each array}}
  <option value="{{code}}">{{name}}</option>
  {{/each}}
  {{/select}}
</select>

matchValue와 array를 넣고 실행해보니 잘 된다. 
같은 방식으로 radio 에도 적용하려고 보니 한 가지 이상한 점이 있다.
<$data:aflkj21j2423> </$data> 형태의 태그가 붙는 것이다.
<option>이야 <select>안쪽에 있어서 상관없지만 <input type="radio"/>같은 경우엔 문제가 된다.

아마 기존 handlebars를 자체는 상관없겠지만 Meteor는 each문에서 특정 object가 갱신이 될때 어떤 걸 다시 만들어야하는지 알기 위해 임의의 인덱스를 필요로 한다.
하지만, 우리는 option이나 radio를 렌더링 하는데 문제가 되므로 정규식을 써서 제거한다.
혹시 이것도 관련있는 사이드 이펙트나 더 좋은 아이디어가 있으면 Meteor_KR(https://plus.google.com/communities/113287389139180020424)에 제보 바란다.

그리하여 최종 작성한 코드는 다음과 같다.
Handlebars.registerHelper "select", (value, options) ->
select = document.createElement("div")
$(select).html options().replace(/<[/]*\$data:\w+>/g, "")
$("input[type=radio]", select).filter("[value='#{value}']").attr "checked", "checked"
$("option", select).filter("[value='#{value}']").attr "selected", "selected"
select.innerHTML
/* js 버전 */
Handlebars.registerHelper("select", function(value, options) {
var html, select;
select = document.createElement("div");
$(select).html(options().replace(/<[/]*\$data:\w+>/g, ""));
$("input[type=radio]", select).filter("[value='" + value + "']").attr('checked', 'checked');
$("option", select).filter("[value='" + value + "']").attr('selected', 'selected');
return select.innerHTML;
});
gist(https://gist.github.com/acidsound/a7de8f12acafc787dff2)에 공유하니 요긴하게 사용하시길.
테스트 해본 결과 리엑티브 객체에서도 잘 동작한다.
체크박스나 다른 커스텀 컨트롤러도 비슷하게 해볼 수 있다.

핸들바의 헬퍼는 참 알아야할 것이 적은 것에 비해 자유도가 높고 강력하다.

2014년 2월 26일 수요일

IE 10에서 JSON object 사용 시 주의점

js에서 JSON에 ,를 잘못 쓰면 IE 10에서 오류 나는 경우 발견.
var obj = {
  a:1,
  b:1
};
이 맞지만
var obj = {
  a:1,
  b:1
};
복사하기 귀찮아서 이렇게 쓰는 라이브러리들이 간혹 있음.
문제는 ,를 쓴 곳에서 오류가 발생하는 것이 아니라 그 이후 라인에서 잘못한 것처럼 보여서 잡아내기 쉽지 않다.
webstorm 같은 구문검사 기능이 있는 에디터를 꼭 쓰자.
아니면 coffeescript를 쓰던가 ;p

2014년 2월 9일 일요일

안드로이드 TV 스틱(armv7l)용 meteor branch를 만들었습니다.

https://github.com/acidsound/meteor/commit/d65a2a3530d89fd97c1b582b00ed28af9c5c608a

수정사항은 위와 같습니다.
필요한 의존성이 있으므로

sudo apt-get update
sudo apt-get install build-essential openssl libssl-dev pkg-config git-core scons libpcre++-dev libboost-dev libboost-program-options-dev libboost-thread-dev libboost-filesystem-dev curl

먼저 받아놓습니다.

설치 방법은
git clone https://github.com/acidsound/meteor.git
cd meteor
git checkout devel_armv7l
./scripts/generate-dev-bundle.sh
이걸로 빌드한 후
./meteor 로 확인해보면 됩니다.

meteor 디렉토리를 path로 잡던가 meteor를 /usr/local/bin 에 넣던(확인 안해봄)하면 됩니다.

meteorite(mrt) 설치는 그냥 npm install 을 사용해서 하면 별 이상 없이 잘 붙습니다.

mongo는 포함하고 있지 않으므로 실행시엔 반드시 외부(ex.mongohq) mongo 서비스를 사용하시길 바랍니다.
MONGO_URL=mongodb://id:pw@alex.mongohq.com:10058/yourdb mrt
식으로 실행하면 됩니다.


2014년 1월 21일 화요일

Cordova(구 phonegap)로 android 앱을 만들 때 GPS 정보를 잘 못 받아온다면.

어떤 폰에선 되고 어떤 폰에선 안되고 되다가도 안되고 하도 현상이 여러가지라서

거의 2주동안 붙잡고 씨름했는데

허무한 결말.

navigator.geolocation.getCurrentPosition(success, failure, option);

에서 option에

{
  timeout: 10000
}

만 줘서 하니 잘 된다.

iOS는 뭐 아무렇게나 해도 잘되는데

Android에선 enableHighAccuracy : true 옵션을 주면 안된다.

나머지는 config.xml에

    <feature name="Geolocation">
        <param name="android-package" value="org.apache.cordova.geolocation.GeoBroker" />
    </feature>

이런게 있는지

platforms/android/AndroidManifest.xml에

가 있는지
....
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />

권한이 잘 들어갔는지

정도만 신경 써주면 된다.

2014년 1월 7일 화요일

Meteor를 client만 사용하기 - Offline Meteor

'뭔소리야 서버부터 클라이언트까지 하나의 언어 하나의 자료형을 쓰는게 Meteor의 장점인데 왜 서버를 분리해?'
라며 당연하고 올바른 생각을 가지고 계신 분이라면 '뒤로 가기' 추천합니다. ^^;;;
Meteor는 좋은데 서버가 자바야, PHP야. 혹은 Cordova(구 phonegap)이나 Chrome Apps같은 분야에 적용하고 싶은데 Meteor로 하고 싶어라고 생각하신다면 추천.

Meteor 프로젝트를 meteor create <...> 로 생성하셨다면 Meteor는 run을 한 시점부터 .meteor/local/build/programs/client 에 클라이언트 쪽 파일들을 생성합니다.

이걸 고대로 떠서 약간의 작업을 하면 서버와 상관없이 사용할 수 있는데.


  1. app.html 의 ##HASH## 들을 삭제한다.
  2. __meteor_runtime_config__ 을 추가하여 ROOT_URL을 지정한다. (보통은 localhost)
  3. package등에서 사용하는 정적 자원에 대한 경로를 수정한다.
8000포트에 할 경우 .html 파일에 아래와 같은 부분을 ##RUNTIME_CONFIG## 있는 곳에 바꿔 넣어줍니다.
  __meteor_runtime_config__={
  ROOT_URL = "http://localhost:8000"
  }

정도가 되겠습니다.
의외로 어렵지 않죠?
근데 실제로 해보면 신경쓸 것들이 좀 있습니다.

제 경우는 디렉토리 구조를 이렇게 잡았습니다.
생성한 과정은 이렇습니다.

$ mkdir pack
$ cd pack
$ meteor create memo
$ mkdir www
$ cd memo

여기까지 하고 client 쪽 코드를 약간 수정합니다.
Meteor는 기본적으로 클라이언트 vs 서버간 websocket통신을 하고 있기 때문에 관련 그 부분을 hack해서 못쓰게 만듭니다.
* memo.js

if (Meteor.isClient) {
  Meteor.connection._stream._retryTimeout = function() { return 365 * 24 * 60 * 60 * 1000 };
  Meteor.connection._stream._lostConnection();
  
  Template.hello.greeting = function () {
    return "Welcome to memo.";
  };

  Template.hello.events({
    'click input' : function () {
      // template data, if any, is available in 'this'
      if (typeof console !== 'undefined')
        console.log("You pressed the button");
    }
  });
}

if (Meteor.isServer) {
  Meteor.startup(function () {
    // code to run on server at startup
  });
}

$ meteor (혹은 meteor --production)
^c (종료)
$ cd ../www
$ cp -R ../memo/.meteor/local/build/programs/client/. .

$ python -m SimpleHTTPServer
(서버구동)

이 정도가 좋은 출발점이지 않을까 싶습니다.
클릭 이벤트도 잘 먹고 괜찮네요.
사실은 sock.js가 계속 뭔가 통신을 하려고 하는데 이 부분은 서버쪽 구현에서 붙여보면 되겠습니다.

Cordova에서 붙여서 프로젝트 하는 용도로 잘 썼구요.
위의 귀찮은 일련의 작업을 자동화할 수 있는 Gruntfile.js의 신세를 졌습니다.
처음 써봤는데 js버전 ant같은 느낌이더군요. 썩 맘에 들지는 않지만 shell을 짜면 OS 의존성이 생기는 걸 생각하면 나쁘지 않더군요.
다음번엔 go 언어에 한번 붙여서 해볼까 합니다.