2012년 2월 24일 금요일

느려터진 안드로이드 에뮬은 버리고 VM을 쓰자.

iOS개발 환경이 안드로이드보다 우월점은 여러가지가 있겠지만
개인적으로 가장 큰부분이라고 생각하는 점이 iOS Simulator 의 넘사벽 속도다.
사실 iOS 의 경우 Emulator 가 아니라 Simulator 라는 훼이크를 써서 그런건데.
하드웨어+소프트웨어를 같이 하는 회사만이 쓸 수 있는 필살기라 볼 수 있다.

반면 안드로이드의 경우 ARM 에뮬레이터를 사용하는데
이게 참 못만들었다.
플스에뮬이나 GBA에뮬 반정도만 만들어도 써줄텐데 아직 갈길이 멀다.
그래서 구시렁 거리면서 하드웨어를 연결해서 테스트를 하고 있는데
역시 USB연결하는 건 불편하고
apk 를 전송하는 과정도 그다지 빠르지 않아서 개발 생산성이 월등히 나아지지는 않는다.
루팅을 하면 wifi 를 통해 apk 를 인스톨 할 수 있다고 해서
몇 가지를 해보았으나 잘 모르겠지만 인스톨까진 잘 되었는데 디버깅 모드로 실행이 되지 않아 그만두었다. 게다가 전송속도도 USB보다 wifi가 느리고 맘에 들지 않더라.
그러던중 stackoverflow.com(늘 신세지고 있습니다) 에서

"VM으로 안드로이드를 띄워서 adb connect 하면 좋아!"
라는 글에 눈이 번쩍.

시행착오를 몇번 했지만 의외로 간단하더라.

1. VMWare건 VirtualBox건 상관없다. VM호스트를 준비하자.
2. http://www.android-x86.org/download 로 가서 Deprecated x86 2.2 generic 을 받자.

Q) 왜 Deprecated 인 2.2 generic 을 받나요. Deprecated는 쓰면 안되는 거 아님?
A) http://mariuz.android-dev.ro/vm.iso.7z 도 있다고 한다. http://www.android-x86.org/download 에 있는 요즘 것들은 죄다 안된다.

3. 죄다 일단 Default 설정에 yes yes 하고 설치한다. 한글 문서가 필요한 분은 "카카오톡 PC"로 검색하면 만족하실만한 내용이 나올 것이다.
4. 부팅 후 Live CD 와 Installation이 나오는데 당연히 Installation
5. Choose Partition / Create/Modify partitions
6. 파티션 만들자. new / primary / bootable / write / yes 하고 quit
7. Choose Partition / sda1 ... 가 첫번째로 추가된 것을 확인하고 엔터
8. ext3 으로 포멧
9. grub 설치 yes
10. /system 디렉토리를 읽고 쓰기할거냐라고 묻는데 맘대로 하세요. yes 했음.
11. Congratulation 나오면 Create a fake SD card 엔터
12. 리붓
13. HDPI 나 MDPI 둘중 선택 (해상도가 다르다)
14. 겁나 빠른 부팅
15. 이 화면을 보았으면 일단 OK
16. alt+f1을 눌러 console 상태로 들어간다.
17. ifconfig eth0 을 입력하여 ethernet 어댑터의 ip 정보를 메모한다.
18. 터미널 혹은 커맨드 창을 열어 adb connect <ip> 때려서 연결

19. 5555 포트에 연결한 것을 확인한다.
20. 수고하셨습니다.

Eclipse/IntelliJ 등에서 실행하면 에뮬레이터가 아니라 연결한다.
말도 안되게 빠르다;;;;;
20MB 넘는 apk파일 구동하는데 업로드에서 인스톨까지 2초면 된다.
게임같이 하드웨어 의존이 많은 어플리케이션이면 모를까 느려터진 에뮬을 쓸 이유가 없다.

ESC,마우스 오른쪽버튼이 Back
Cmd(아마 윈도우에선 윈도우키?) 키가 HOME
F4, ALT+F6 F6 이 전원 버튼 꾸욱
ALT+F1 이 console mode
ALT+F7 이 복귀
ALT+F3 이 Call log

대충 이정도 메뉴키는 뭔지 모르겠다. windows 에선 윈도우키라는 소리가 있다.

F2 가 메뉴키다.

* VirtualBox 에서 팁.
VMWare 에 비해 크게 다른 점은 없으나
adb connect 가 안될 수 있다.
그럴땐 네트워크에서 포트포워딩 설정을 하면 된다.
(http://dev.blogs.nuxeo.com/2011/10/speeding-up-the-android-emulator.html 댓글내용중 참조)

네트워크 설정으로 들어가서
5555번 포트 포워딩을 설정한다.


그리고 adb connect  127.0.0.1 로 연결하면 된다.
https://www.facebook.com/note.php?note_id=287370717967718
해상도 설정 관련하여 잘 정리해주신 분이 계신다. 고맙습니다.

2012년 2월 23일 목요일

javascript 3d round carousel

http://jsdo.it/spectrum/carousel
역시나 맘에 드는게 없어서 만들었다.
어렵지 않을려나 싶었는데 생각보다 얼마 안걸림.
역시 모닝 코딩인가.
querySelectorAll 때문에 $s 랑, items() 를 프로토타입에서 array를 반환하도록 하여 forEach를 돌릴 수 있도록 소금(salt)을 쳤다.
var $=function(selector) {
    return document.querySelector(selector);
};

var $s=function(selector) {
    return document.querySelectorAll(selector);
};

NodeList.prototype.items=function() { 
    var array=[]; 
    for (var i=0; i [2, 0] (뒤집힘)
     // / 2   하면     [1, 0]이 됨.
     // * (1-2/5) 하면 [3/5, 0]
     // 1 -   하면     [2/5, 1]
     var scale = (1-(1-Math.sin(degree*Math.PI/180))/2*(1-2/5));
     v.setAttribute('style', 
      'left:'+parseInt(x,10)+'px;'+ 
      'top:'+parseInt(y,10)+'px;'+
      'z-index:'+parseInt(y,10)+';'+
      '-webkit-transform: scale('+scale+');'
     );
 });
    }
};
document.ontouchmove = function(e){ e.preventDefault(); };
p.objects=$s('ul#container>li');
p.renderCarousel(p.idx);
window.onload=p.onLoad;

ul 안에 li를 몇개든 넣어보자.
중심을 기준으로 반지름은 100px, 종횡비는 2/5:1 정도인데 입맛대로 수정하면 됨.

2012년 2월 20일 월요일

html5 audio player를 만들어 보았다. #2

html5 audio player를 만들어 보았다.
에서 언급했던 audio player 를 조금 업데이트.

마찬가지로 소스는 이곳 : http://jsdo.it/spectrum/webAudioPlayer
플레이 전용(모바일 등등)은 http://jsrun.it/spectrum/webAudioPlayer

전체 시간을 보여주고 재생 배속을 설정할 수 있다.
소스는 대동소이.
duration 을 사용. 전체 재생 길이를 보여주고
playbackRate 으로 재생 배속을 변경하도록 하였다.
http://dev.w3.org/html5/spec/Overview.html#htmlmediaelement
의외로 오디오 재생 피치를 유지한 상태로 정말 배속만 변하더라.
double 값이라서 세세한 조정은 가능함.
아쉽게도 android/iOS에서는 배속 지원은 안함.
$=function(element) { 
    return document.querySelector(element);
};
p={
    audio : null,
    onLoad: function() {
 p.audio = new Audio('http://k003.kiwi6.com/hotlink/3dgmyavs49/your_name_ft_gaduk.mp3');
 $('#play').onclick=p.onPlay;
 $('#stop').onclick=p.onStop;
 $('#pause').onclick=p.onPause;
 $('#rew10').onclick=p.on10rew;
 $('#ff10').onclick=p.on10ff;
 $('#rate').onclick=p.onRate;
 p.audio.addEventListener('timeupdate', p.onTimeUpdate, false);
    },
    onPlay: function() {
 p.audio.play();
    },
    onStop: function() {
 p.audio.currentTime = 0;
 p.onPause();
    },
    onPause: function() {
 p.audio.pause();
    },
    on10rew: function() {
 p.audio.currentTime -=10;
    },
    on10ff: function() {
 p.audio.currentTime +=10;
    },
    onRate: function() {
 var rate = $('#rate').textContent;
 $('#rate').textContent= rate === '1x' ? '2x' : rate === '2x' ? '1/2x' : '1x';
 rate = $('#rate').textContent;
 p.audio.playbackRate = rate === '1x' ? 1.0 : rate=== '2x' ? 2.0 : 0.5;
    },
    onTimeUpdate : function() {
 var currTime = p.audio.currentTime;
 $('#time').textContent=parseInt(currTime/60,10)+':'+
     parseInt(currTime%60,10) + '/' + 
     parseInt(p.audio.duration/60,10)+':'+
     parseInt(p.audio.duration%60,10);
    }
};
window.onload=p.onLoad;

2012년 2월 16일 목요일

routing module을 만들자 - handler

callback을 바로 넣을 수는 없어보이고
type 에 func 을 정의하고 달면 된다.
나름 명시적이네.

역시 소스는 여기

package main

import (
  "fmt"
)

type Handler func(method string)

type Route struct {
  Method,Pattern string
}

type Routes struct {
  Routes []Route
}
func (r Routes) routeCount() int {
  return len(r.Routes)
}
func (r *Routes) addRoute(method, pattern string, handler Handler) {
  r.Routes=append(r.Routes, Route{Method:method, Pattern:pattern})
  fmt.Printf("route Count : %d\n", len(r.Routes))
  handler(method)
}
func (r *Routes) GET(pattern string, handler Handler) {
  r.addRoute("GET", pattern, handler)
}
func (r *Routes) POST(pattern string, handler Handler) {
  r.addRoute("POST", pattern, handler)
}
func (r *Routes) PUT(pattern string, handler Handler) {
  r.addRoute("PUT", pattern, handler)
}
func (r *Routes) DELETE(pattern string, handler Handler) {
  r.addRoute("DELETE", pattern, handler)
}
func handler(method string) {
  fmt.Printf("%s handler executed \n", method)
}

func main() {
  r:=new(Routes)
  r.GET("/user/:user", handler)
  r.PUT("/add/:user", handler)
  r.POST("/update/:user", handler)
  r.DELETE("/delete/:user", handler)
  for _,v:=range r.Routes {
    fmt.Printf("%s:%s\n",v.Method, v.Pattern)
  }
}


------
의도는 이게 아닌데 빨리 무엇이든 달아보고 싶었다.

route Count : 1
GET handler executed 
route Count : 2
PUT handler executed 
route Count : 3
POST handler executed 
route Count : 4
DELETE handler executed 
GET:/user/:user
PUT:/add/:user
POST:/update/:user
DELETE:/delete/:user

routing module을 만들자 - REST 붙이기

별 중요한 건 없지만 역시 func (variable struct)를 쓰는 패턴을 학습한다.
routeCount 를 구할땐 func(r Routes)를
addRoute, GET/POST/PUT/DELETE를 할땐 func(r *Routes) 를 쓰는 부분에 주목하자.

역시 소스는 여기
package main

import (
  "fmt"
)

type Route struct {
  Method,Pattern string
}
type Routes struct {
  Routes []Route
}
func (r Routes) routeCount() int {
  return len(r.Routes)
}
func (r *Routes) addRoute(method, pattern string) {
  r.Routes=append(r.Routes, Route{Method:method, Pattern:pattern})
  fmt.Printf("route Count : %d\n", len(r.Routes))
}
func (r *Routes) GET(pattern string) {
  r.addRoute("GET", pattern)
}
func (r *Routes) POST(pattern string) {
  r.addRoute("POST", pattern)
}
func (r *Routes) PUT(pattern string) {
  r.addRoute("PUT", pattern)
}
func (r *Routes) DELETE(pattern string) {
  r.addRoute("DELETE", pattern)
}
func main() {
  r:=new(Routes)
  r.GET("/user/:user")
  r.PUT("/add/:user")
  r.POST("/update/:user")
  r.DELETE("/delete/:user")
  for _,v:=range r.Routes {
    fmt.Printf("%s:%s\n",v.Method, v.Pattern)
  }
}

------
결과는 아래와 같다.
거의 준비가 다 되었다.
내일은 package 를 분리하고 handler를 달아봐야지.
route Count : 1
route Count : 2
route Count : 3
route Count : 4
GET:/user/:user
PUT:/add/:user
POST:/update/:user
DELETE:/delete/:user

go 공부 - struct에 대하여


routing module 을 만들기 위해 객체를 작성해야겠다는 생각이 들어 struct와 function을 보고 있다.
아무래도 나온지 2년이나 되었지만 인지도가 약해서인지 제대로 돌아가는 소스가 적다.
직접 해보고 오류 메시지를 보면서 학습할 수 밖에.

go는 javascript 처럼 functional하기도 하고 prototypal 한 특성을 가지고 있다.
function 을 이용하는 법을 보고 있는데
얼추 비슷하게 쓸 수 있겠다.

http://golang.org/doc/ExpressivenessOfGo.pdf 중 21page 를 보면서 소스를 타이핑 해본다.

소스보기
package main


import (
  "fmt"
  "math"
)

type Point struct { x, y float64 }
func (p Point) Abs() float64 {
  return math.Sqrt(p.x*p.x + p.y*p.y)
}

func main() {
  p:=Point{3,4}
  fmt.Printf("%f", p.Abs())
}

객체를 생성할땐 pascal 타입의 선언자 := 를 써서 쓸 수도 있고
다른 언어들처럼 new를 써서 main부분을 바꿔보면.

func main() {
  p:=new(Point)
  p.x = 3
  p.y = 4
  fmt.Printf("%f", p.Abs())
}
이런식으로 초기화 할 수도 있다.


아마도 javascript 로 쓰면 아래와 같을 것이다.
var Point = function(arg) {
  var x;
  var y;
  x=arg.x;
  y=arg.y;
  return {
    Abs : function() {
      return Math.sqrt(x*x,y*y);
    }
  }
}
var p = new Point({x:3,y:4});
console.log(p.Abs());

이정도쯤 되겠네.
이렇게 비교하면서 보니까 상당히 괜찮군. 여러가지 생각이 든다.
func (p Point) 부분이 좀 어색하고 중복이 느껴지긴 한데 익숙해지면 재미있는 표현법이겠다.

2012년 2월 15일 수요일

go용 routing module을 만들고 있다.

ror/sinatra 나 express.js 처럼 우아한 routing쓰고 싶은데
연습삼아 만들어보자는 생각에 서툰 코딩을 시작
/user/:userid 인 경우 \/user\/([^\/]+)\/? 이런 식으로 우아하게 정규식 치환을 했으면 했는데
string 패키지도 좀 볼겸. 단순하게 문자열 조작+뺑뺑이로 구현했다.
https://gist.github.com/1827639


package main
import "fmt"
import "strings"
var routes = []string{
  "/user/:id/friends/:friendsId",
  "/scrapbook/:scrapbookid/scrap/:scrapid",
  "/"}
func getParams(url string) map[string]string {
  for idx,_:=range routes {
    format := routes[idx]
    urlToken := strings.Split(url, "/")
    formatToken := strings.Split(format, "/")
    /* match pattern */
    if len(urlToken)==len(formatToken) && len(formatToken)>0 {
      params := make(map[string]string)
      match := true
      for i,v:=range formatToken {
        if len(v)>0 && v[0:1] == ":" {
          params[v[1:]]=urlToken[i]
        } else if v!=urlToken[i] {
          match =false
        }
      }
      if match {
        return params
      }
    }
  }
  return nil
}
func main() {
  for i,v:=range getParams("/scrapbook/1ABCDE/scrap/401") {
    fmt.Printf("[%s:%s]",i,v)
  }
  fmt.Println("")
  for i,v:=range getParams("/user/spectrum/friends/cid") {
    fmt.Printf("[%s:%s]",i,v)
  }
  fmt.Println("")
  for i,v:=range getParams("/root") {
    fmt.Printf("[%s:%s]",i,v)
  }
  fmt.Println("")
}


웹에서 코드실행


/user/:id/friends/:friendsId
/scrapbook/:scrapbookid/scrap/:scrapid

에서 각각 :으로 시작하는 인자값을 뽑아낸다.

정적 타이핑 언어치고 재미있네. 에휴 Dennis Ritchie옹 생각에 눙무리 ;;ㅅ;;