Interesting/ANDROID | Posted by hyena0 2009. 7. 7. 02:49

[android] 나침반 + 구글지도


  나침반 + 구글지도

  안드로이드에서 구글지도를 

  보이게 하는 것은 검색페이지에서 쉽게 찾을 수 있다.

  안드로이드의 센서 중 하나인

  나침반을 이용해서 구글지도와 연결하면

  핸드폰을 가지고 방향만 틀어도 지도를 볼 수 있게 된다.

  여기서 센서의 방향 값을 가지고 지도를 회전할 수 있게 해야 하는게 관건인데

  아래의 샘플코드를 보면 센서값 중 heading 값을 가지고 평면의 회전 각도를 입력한다.

  아래 코드는 MapViewCompassDemo.java를 수정한 것이다. 

  SDK 1.5 맞게 수정했으므로 한번 시험해 보면 동작을 확인해 볼 수 있다. 

  여기서 중요한 건 MapActivity 로 상속받아 사용할때 Manifest 파일을 수정해야 한다는 것과

  프로젝트 속성에서 Build Target을 Google API로 해놓고 해야 한다는 것이다.

package <<당신의 패키지 이름>>;


import javax.microedition.khronos.opengles.GL;


import android.os.Bundle;

import android.view.MotionEvent;

import android.view.View;

import android.view.ViewGroup;

import android.content.Context;

import android.graphics.Bitmap;

import android.graphics.Canvas;

import android.graphics.DrawFilter;

import android.graphics.Matrix;

import android.graphics.Paint;

import android.graphics.Path;

import android.graphics.Picture;

import android.graphics.PorterDuff;

import android.graphics.Rect;

import android.graphics.RectF;

import android.graphics.Region;

import android.hardware.Sensor;

import android.hardware.SensorManager;

import android.hardware.SensorEventListener;

import android.hardware.SensorEvent;


import com.google.android.maps.MapActivity;

import com.google.android.maps.MapView;

import com.google.android.maps.MyLocationOverlay;


/**

 * Example of how to use an {@link com.google.android.maps.MapView}

 * in conjunction with the {@link com.hardware.SensorManager}

 * <h3>MapViewCompassDemo</h3>


<p>This demonstrates creating a Map based Activity.</p>


<h4>Source files</h4>

 * <table class="LinkTable">

 *         <tr>

 *             <td >src/com/android/samples/view/MapViewCompassDemo.java</td>

 *             <td >The Alert Dialog Samples implementation</td>

 *         </tr>

 * </table>

 */

public class rotatableMap extends MapActivity {


    private SensorManager mSensorManager;

    private RotateView mRotateView;

    private MapView mMapView;

    private MyLocationOverlay mMyLocationOverlay;


    private class RotateView extends ViewGroup implements SensorEventListener {

                                           //v1.5 부터는 SensorEventListener를 이용합니다.

        private static final float SQ2 = 1.414213562373095f;

        private final SmoothCanvas mCanvas = new SmoothCanvas();

        private float mHeading = 0;


        public RotateView(Context context) {

            super(context);

        }


        public void onSensorChanged(SensorEvent sensorEvent) {

            synchronized (this) {

                mHeading = sensorEvent.values[0];  // 센서 값중 Heading 값만 가져갑니다.

                invalidate();

            }

        }

        public void onAccuracyChanged(Sensor sensor, int accuracy){

    }

        

        @Override

        protected void dispatchDraw(Canvas canvas) {

            canvas.save(Canvas.MATRIX_SAVE_FLAG);

            canvas.rotate(-mHeading, getWidth() * 0.5f, getHeight() * 0.5f);

            mCanvas.delegate = canvas;

            super.dispatchDraw(mCanvas);

            canvas.restore();

        }


        @Override

        protected void onLayout(boolean changed, int l, int t, int r, int b) {

            final int width = getWidth();

            final int height = getHeight();

            final int count = getChildCount();

            for (int i = 0; i < count; i++) {

                final View view = getChildAt(i);

                final int childWidth = view.getMeasuredWidth();

                final int childHeight = view.getMeasuredHeight();

                final int childLeft = (width - childWidth) / 2;

                final int childTop = (height - childHeight) / 2;

                view.layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight);

            }

        }



        @Override

        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

            int w = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);

            int h = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);

            int sizeSpec;

            if (w > h) {

                sizeSpec = MeasureSpec.makeMeasureSpec((int) (w * SQ2), MeasureSpec.EXACTLY);

            } else {

                sizeSpec = MeasureSpec.makeMeasureSpec((int) (h * SQ2), MeasureSpec.EXACTLY);

            }

            final int count = getChildCount();

            for (int i = 0; i < count; i++) {

                getChildAt(i).measure(sizeSpec, sizeSpec);

            }

            super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        }


        @Override

        public boolean dispatchTouchEvent(MotionEvent ev) {

            // TODO: rotate events too

            return super.dispatchTouchEvent(ev);

        }

    }


    @Override

    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);


        //original

        //requestWindowFeature(Window.FEATURE_OPENGL);


        mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);

        mRotateView = new RotateView(this);

        mMapView = new MapView(this, "06MmQkkJlMQtcbbaAI1Njy1JcO39_F4DrwR-cpA");

        mRotateView.addView(mMapView);

        setContentView(mRotateView);


        mMyLocationOverlay = new MyLocationOverlay(this, mMapView);

        mMyLocationOverlay.runOnFirstFix(new Runnable() { public void run() {

            mMapView.getController().animateTo(mMyLocationOverlay.getMyLocation());

        }});

        mMapView.getOverlays().add(mMyLocationOverlay);

        mMapView.getController().setZoom(18);

        mMapView.setClickable(true);

        mMapView.setEnabled(true);

    }


    @Override

    protected void onResume() {

        super.onResume();

        mSensorManager.registerListener(mRotateView,

        mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION),

                SensorManager.SENSOR_DELAY_UI);

        mMyLocationOverlay.enableMyLocation();

    }


    @Override

    protected void onStop() {

        mSensorManager.unregisterListener(mRotateView);

        mMyLocationOverlay.disableMyLocation();

        super.onStop();

    }


    @Override

    protected boolean isRouteDisplayed() {

        return false;

    }



    static final class SmoothCanvas extends Canvas {

        Canvas delegate;


        private final Paint mSmooth = new Paint(Paint.FILTER_BITMAP_FLAG);


        public void setBitmap(Bitmap bitmap) {

            delegate.setBitmap(bitmap);

        }


        public void setViewport(int width, int height) {

            delegate.setViewport(width, height);

        }


        public boolean isOpaque() {

            return delegate.isOpaque();

        }


        public int getWidth() {

            return delegate.getWidth();

        }


        public int getHeight() {

            return delegate.getHeight();

        }


        public int save() {

            return delegate.save();

        }


        public int save(int saveFlags) {

            return delegate.save(saveFlags);

        }


        public int saveLayer(RectF bounds, Paint paint, int saveFlags) {

            return delegate.saveLayer(bounds, paint, saveFlags);

        }


        public int saveLayer(float left, float top, float right, float

                bottom, Paint paint,

                int saveFlags) {

            return delegate.saveLayer(left, top, right, bottom, paint,

                    saveFlags);

        }


        public int saveLayerAlpha(RectF bounds, int alpha, int saveFlags) {

            return delegate.saveLayerAlpha(bounds, alpha, saveFlags);

        }


        public int saveLayerAlpha(float left, float top, float right,

                float bottom, int alpha,

                int saveFlags) {

            return delegate.saveLayerAlpha(left, top, right, bottom,

                    alpha, saveFlags);

        }


        public void restore() {

            delegate.restore();

        }


        public int getSaveCount() {

            return delegate.getSaveCount();

        }


        public void restoreToCount(int saveCount) {

            delegate.restoreToCount(saveCount);

        }


        public void translate(float dx, float dy) {

            delegate.translate(dx, dy);

        }


        public void scale(float sx, float sy) {

            delegate.scale(sx, sy);

        }


        public void rotate(float degrees) {

            delegate.rotate(degrees);

        }


        public void skew(float sx, float sy) {

            delegate.skew(sx, sy);

        }


        public void concat(Matrix matrix) {

            delegate.concat(matrix);

        }


        public void setMatrix(Matrix matrix) {

            delegate.setMatrix(matrix);

        }


        public void getMatrix(Matrix ctm) {

            delegate.getMatrix(ctm);

        }


        public boolean clipRect(RectF rect, Region.Op op) {

            return delegate.clipRect(rect, op);

        }


        public boolean clipRect(Rect rect, Region.Op op) {

            return delegate.clipRect(rect, op);

        }


        public boolean clipRect(RectF rect) {

            return delegate.clipRect(rect);

        }


        public boolean clipRect(Rect rect) {

            return delegate.clipRect(rect);

        }


        public boolean clipRect(float left, float top, float right,

                float bottom, Region.Op op) {

            return delegate.clipRect(left, top, right, bottom, op);

        }


        public boolean clipRect(float left, float top, float right,

                float bottom) {

            return delegate.clipRect(left, top, right, bottom);

        }


        public boolean clipRect(int left, int top, int right, int bottom) {

            return delegate.clipRect(left, top, right, bottom);

        }


        public boolean clipPath(Path path, Region.Op op) {

            return delegate.clipPath(path, op);

        }


        public boolean clipPath(Path path) {

            return delegate.clipPath(path);

        }


        public boolean clipRegion(Region region, Region.Op op) {

            return delegate.clipRegion(region, op);

        }


        public boolean clipRegion(Region region) {

            return delegate.clipRegion(region);

        }


        public DrawFilter getDrawFilter() {

            return delegate.getDrawFilter();

        }


        public void setDrawFilter(DrawFilter filter) {

            delegate.setDrawFilter(filter);

        }


        public GL getGL() {

            return delegate.getGL();

        }


        public boolean quickReject(RectF rect, EdgeType type) {

            return delegate.quickReject(rect, type);

        }


        public boolean quickReject(Path path, EdgeType type) {

            return delegate.quickReject(path, type);

        }


        public boolean quickReject(float left, float top, float right,

                float bottom,

                EdgeType type) {

            return delegate.quickReject(left, top, right, bottom, type);

        }


        public boolean getClipBounds(Rect bounds) {

            return delegate.getClipBounds(bounds);

        }


        public void drawRGB(int r, int g, int b) {

            delegate.drawRGB(r, g, b);

        }


        public void drawARGB(int a, int r, int g, int b) {

            delegate.drawARGB(a, r, g, b);

        }


        public void drawColor(int color) {

            delegate.drawColor(color);

        }


        public void drawColor(int color, PorterDuff.Mode mode) {

            delegate.drawColor(color, mode);

        }


        public void drawPaint(Paint paint) {

            delegate.drawPaint(paint);

        }


        public void drawPoints(float[] pts, int offset, int count,

                Paint paint) {

            delegate.drawPoints(pts, offset, count, paint);

        }


        public void drawPoints(float[] pts, Paint paint) {

            delegate.drawPoints(pts, paint);

        }


        public void drawPoint(float x, float y, Paint paint) {

            delegate.drawPoint(x, y, paint);

        }


        public void drawLine(float startX, float startY, float stopX,

                float stopY, Paint paint) {

            delegate.drawLine(startX, startY, stopX, stopY, paint);

        }


        public void drawLines(float[] pts, int offset, int count, Paint paint) {

            delegate.drawLines(pts, offset, count, paint);

        }


        public void drawLines(float[] pts, Paint paint) {

            delegate.drawLines(pts, paint);

        }


        public void drawRect(RectF rect, Paint paint) {

            delegate.drawRect(rect, paint);

        }


        public void drawRect(Rect r, Paint paint) {

            delegate.drawRect(r, paint);

        }


        public void drawRect(float left, float top, float right, float

                bottom, Paint paint) {

            delegate.drawRect(left, top, right, bottom, paint);

        }


        public void drawOval(RectF oval, Paint paint) {

            delegate.drawOval(oval, paint);

        }


        public void drawCircle(float cx, float cy, float radius, Paint paint) {

            delegate.drawCircle(cx, cy, radius, paint);

        }


        public void drawArc(RectF oval, float startAngle, float

                sweepAngle, boolean useCenter,

                Paint paint) {

            delegate.drawArc(oval, startAngle, sweepAngle, useCenter, paint);

        }


        public void drawRoundRect(RectF rect, float rx, float ry, Paint paint) {

            delegate.drawRoundRect(rect, rx, ry, paint);

        }


        public void drawPath(Path path, Paint paint) {

            delegate.drawPath(path, paint);

        }


        public void drawBitmap(Bitmap bitmap, float left, float top,

                Paint paint) {

            if (paint == null) {

                paint = mSmooth;

            } else {

                paint.setFilterBitmap(true);

            }

            delegate.drawBitmap(bitmap, left, top, paint);

        }


        public void drawBitmap(Bitmap bitmap, Rect src, RectF dst,

                Paint paint) {

            if (paint == null) {

                paint = mSmooth;

            } else {

                paint.setFilterBitmap(true);

            }

            delegate.drawBitmap(bitmap, src, dst, paint);

        }


        public void drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) {

            if (paint == null) {

                paint = mSmooth;

            } else {

                paint.setFilterBitmap(true);

            }

            delegate.drawBitmap(bitmap, src, dst, paint);

        }


        public void drawBitmap(int[] colors, int offset, int stride,

                int x, int y, int width,

                int height, boolean hasAlpha, Paint paint) {

            if (paint == null) {

                paint = mSmooth;

            } else {

                paint.setFilterBitmap(true);

            }

            delegate.drawBitmap(colors, offset, stride, x, y, width,

                    height, hasAlpha, paint);

        }


        public void drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint) {

            if (paint == null) {

                paint = mSmooth;

            } else {

                paint.setFilterBitmap(true);

            }

            delegate.drawBitmap(bitmap, matrix, paint);

        }


        public void drawBitmapMesh(Bitmap bitmap, int meshWidth, int

                meshHeight, float[] verts,

                int vertOffset, int[] colors, int colorOffset, Paint paint) {

            delegate.drawBitmapMesh(bitmap, meshWidth, meshHeight,

                    verts, vertOffset, colors,

                    colorOffset, paint);

        }


        public void drawVertices(VertexMode mode, int vertexCount,

                float[] verts, int vertOffset,

                float[] texs, int texOffset, int[] colors, int

                colorOffset, short[] indices,

                int indexOffset, int indexCount, Paint paint) {

            delegate.drawVertices(mode, vertexCount, verts,

                    vertOffset, texs, texOffset, colors,

                    colorOffset, indices, indexOffset, indexCount, paint);

        }


        public void drawText(char[] text, int index, int count, float

                x, float y, Paint paint) {

            delegate.drawText(text, index, count, x, y, paint);

        }


        public void drawText(String text, float x, float y, Paint paint) {

            delegate.drawText(text, x, y, paint);

        }


        public void drawText(String text, int start, int end, float x,

                float y, Paint paint) {

            delegate.drawText(text, start, end, x, y, paint);

        }


        public void drawText(CharSequence text, int start, int end,

                float x, float y, Paint paint) {

            delegate.drawText(text, start, end, x, y, paint);

        }


        public void drawPosText(char[] text, int index, int count,

                float[] pos, Paint paint) {

            delegate.drawPosText(text, index, count, pos, paint);

        }


        public void drawPosText(String text, float[] pos, Paint paint) {

            delegate.drawPosText(text, pos, paint);

        }


        public void drawTextOnPath(char[] text, int index, int count,

                Path path, float hOffset,

                float vOffset, Paint paint) {

            delegate.drawTextOnPath(text, index, count, path, hOffset,

                    vOffset, paint);

        }


        public void drawTextOnPath(String text, Path path, float

                hOffset, float vOffset,

                Paint paint) {

            delegate.drawTextOnPath(text, path, hOffset, vOffset, paint);

        }


        public void drawPicture(Picture picture) {

            delegate.drawPicture(picture);

        }


        public void drawPicture(Picture picture, RectF dst) {

            delegate.drawPicture(picture, dst);

        }


        public void drawPicture(Picture picture, Rect dst) {

            delegate.drawPicture(picture, dst);

        }

    }

}




  JotNot

  아이폰 용으로 이전에 한번 소개한 적이

  있는 어플이다. 

  안드로이드 용으로 다운로드 받아서 사용해 보니

  아이폰 용에서 설명한 것처럼 변환할

  네 귀퉁이를 입력받지 않고 자동으로 코너를 계산해서

  결과를 표시해 주었다. 

  내가 에뮬레이터에서 이미지 프로세싱한 결과가 너무 느려서

  프로그램을 잘못 짜서 그런가 하고 생각했는데, JotNot 도 변환시에 속도가 느린것은 마찬가지 였다.

  아래는 스크린 샷이다. 

   JotNot 아이콘을 선택하여 실행한다.



다음과 같은 초기 화면이 나오고 사진기 모양을 선택하면 사진을 찍을 수 있다. 


 적당한 위치에서 사진을 찍고 저장한다.


  그리고 View 메뉴를 선택하면 변환되고 있는 것을 볼 수 있다.


  변환이 완료되면 다음의 이미지가 보인다.



  이와 유사한 프로그램이 "Share your whiteboard"라는 프로그램이 있는데, 

  위에 아이콘들있는 그림에 보면 좌측 맨 아래에 있다. 

  인식률이 떨어져서 변환하면 결과가 이상한 부분을 확대한 결과로 나올때가 종종 있어서 

  추천하고 싶지 않다. 

  JotNot의 경우는 15일간만 무료로 사용가능하다. 


  맥북 구입하다

  해킨토시로 어느정도 맥에 적응해 가고 있는데,

  주말의 잦은 이동으로 인해 노트북이 필요하게 되었다.

  경제사정으로 넷북을 살까도 고민했지만

  개발을 할 수 있는 환경은 안된다는 주변 사용자들의

  말에 노트북이 낫겠다는 결정을 했다.

  하지만, 또 노트북으로 해킨을 한다는 것은 정말로

  소모적인 일일 것이다. 그래서 어짜피 맥에서도

  안드로이드개발할 수 있고, 아이폰도 개발할 수 있고

  맥으로 전향하게 되었다. 

  최근 애플 사이트에서 연속해서 제품이 나온걸로 볼때

  지금 신형 맥북이 나온 관계로 아마도 구형맥북이 리퍼브 상품으로 나오고 있는 것

  같다는 생각이 든다. 

  그래서 나름 노하우로 이전버전의 맥북을 저렴한 가격에 구입하게 되었다.

 개봉하다

  배송은 24시간내라고 되어있었는데, 정말로 주문한지 24시간 안에 배달되었다.

  배송은 TNT 라는 업체에서 배송했고 리퍼브 상품이라 그런지 박스는 애플로고가 없었다.
 

박스를 열어보니 또하나의 박스가 있고 그 아래 맥북이 있었다.


박스를 개봉하니 어댑터와 설치DVD, 화면클리너 천, 매뉴얼, 품질보증서 등이 들어 있었다.


맥북프로는 알루미늄의 바디를 가지고 있었다.


비닐로 포장이 되어 있었는데, 비닐을 뜯으면 자동적으로 품질보증서를 뜯게 되어 있었다.


모니터를 열어보니 LED를 적용한 얇은 화면이 나왔다.


전원을 켜니 애플로고가 나오고 환영합니다 라는 메시지와 함께 X 표시가 나왔다.


이후 몇가지 업데이트를 진행했다. 10.5.6 버전으로 설정이 되어 있어서 10.5.7로 버전을 올리고  Safari 버전도 4.0 으로 올리는 등의 작업을 수행하니 시간이 훌쩍 지나갔다.

화면이 좀 작은게 아쉽긴 하지만 이동성을 위해서는 적합한 크기라 생각된다.