2014년 2월 12일 수요일

페블와치(Pebble Smart Watch) 한글유저 사용을 위한 환경설정 방법



페블와치(Pebble Smart Watch) 한글유저 사용을 위한 환경설정 방법








참고)

페블와치 구입 : 중고나라 (검색어 : pebble)
페블와치 중고가 : 17만3천원 (체리레드 색)
페블와치 시리얼버전 : 숫자로시작
페블와치에서 가장 많이 사용하는 기능 : 문자, 전화, 각종 메신저앱 알림내용 수신 그리고, 시간과 날짜확인, 핸드폰찾기




환경설정)

1. 폰에 안드로이드 pebble 앱 설치

2. pebble 앱 실행

3. 폰에 블루투스 on

4. pebble 시계와 폰간에 페어링 맺기 ( 폰에서 먼저 페어링 질문팝업 뜨면 확인 누르고 시계에서 v 표시위치 버튼 누름)
=> 페어링이 시계에서 잘 안되는 경우가 있음, 시계에서 페어링 맺으려고시도한 폰 이름을 삭제. 폰에서도 블루투스 off 했다가 다시 on 해서 제 시도 하면 됨.

5. 폰에서 환경설정 > 접근성 > pebble 사용으로 변경 (모든 pebble용 안드로이드 앱은 이 내용들 확인하여 사용으로 해줘야 앱을 사용할 수 있음.)

6. 폰에서 pebble 앱실행. 

7. 폰에서의 pebble 앱 화면가운데 connect 버튼으로 앱과 pebble와치 연결.( 연결이 안되면, 4.번의 페어링 맺기 다시 시도)

8. 한글 펌웨어 설치 (한국어 사용자라면...)
한글 펌웨어 링크 : http://ipkn.github.io/pebble 및 제작자 ipknhama@gmail.com
=> 링크에 들어가면 상단에 최신 펌웨어 버전의 두개 링크가 있다. 해당하는 링크를
폰의 브라우저에서 들어가 펌웨어파일링크를 클릭하여 다운받은다음, 폰에 있는 파일관리자
앱(Astro 앱 등등)으로 다운받은 펌웨어 파일을 클릭하면, 자동으로 pebble 앱에 의해 pebble 시계에 한글펌웨어가 설치된다.

9. 설치 완료되면 완료 한글문구가 표시될 것이다.

10. 한글펌웨어가 2.0최신기반의 펌웨어이기 때문에 폰에 설치한 pebble앱도 최신 버전으로 변경해 줘야 pebble watch app(시계에 설치되는 스킨및 앱)들을 설치할 수 있다.

11. pebble 최신 펌웨어에 대한 앱은 아직 beta버전으로 마켓에서는 받을수없으므로 별도로 pebble 홈페이지에서 받을 수 있다.

=> 현재시점에서의 최신베타 버전 앱에 대한 링크이다. 시간이 오래되면 최신 글을 참고하도록.(https://developer.getpebble.com/blog/)

12. 폰에서 위 링크에 들어가서 download android beta9 클릭하여 앱을 다운 받은수 역시 파일관리자앱(Astro 앱등등)을 이용하여 폰에 설치한다.

13. 폰에 설치해둔 pebble 앱이 최신 베타버전앱으로 변경된 것을 확인할수있다.

14. 앱과 시계를 다시 connect 한다.(자동으로 connect 되기도함.)

15. 한글펌웨어2.0 설치 후에도 watch app들 설치가 가능해졌으나, pebble 펌웨어2.0에서의 버그인지, 한글펌웨어2.0에서의 버그인지.. 잘 모르겠지만, 일부앱(상당히많은..)들 사용시, app crash 가뜨면서 정상작동 못하는 경우가 있으니, 앱을 잘 골라서 사용한다.

16. 한글펌웨어2.0설치를하면, 문자와 전화 알림은 잘들어오는데, 각종 핸드폰 앱에서의 알림은 들어오지 않는다.

17. 15번에서 처럼 watch app으로써 알림을 수신받는 앱들은 app crash 가 떠서 사용못하고, 안드로이드 앱으로써 pebble 시계에 알림을 전달해주는 앱들의 대부분은 한글펌웨어2.0과의 호한 또는 버그 문제로 역시 알림수신을 제대로 수행해주지못한다.
그 중에, 알림수신을 해주는 놈을 찾았다.

1) 사용했던 의견 1 : Pebble Notifier Korean Edition 앱이다. 마켓에서 검색하면 찾을 수 있다. 이 앱은 알림내용을 시계에 전달해주는데 한글을 영문으로 표기해준다.(예) 사랑해 -> sa.lang.he) 내용이 많으면 읽기 불편하지만, 어째든 임무수행은 해주니 사용하는게 좋다. 하지만, 이 앱도 가끔 카톡등 알림이 안들어올때가 있기는하다. 하지만 다른 앱보다는 잘들어와서 추천한다.

2) 사용했던 의견 2 : Pebble Notifier 앱. 몇번설치해도 알림이 안됬는데, 몇번 다시 설치해보니 모든 앱들의 알림이 잘들어온다.




2014년 1월 27일 월요일

Fragment 에서 서버에서 받은 이미지로 무한 반복 드래그 ViewPager 구현.


Fragment 에서 서버에서 받은 이미지로 무한 반복 드래그 ViewPager 구현.

ViewPager는 드래그할 경우, 앞뒤 이미지를 생성해 둔 상태에서 동작한다. 따라서 무한 드래그구현시, 마지막 끝에서도 맨첫번째 이미지가 드래그 되도록 하기위해서, 이미 첫번째 이미지가 끝에 이어서 생성되어있어야 한다. 따라서, 프로그램상으로는 실제  view(여기선 이미지)에 사용하는 개수는 실재view의 개수의 3배로 설정한다. 

@Override public int getCount() { return (mProductCnt * 3); }

그리고, 
@Override public void onPageSelected(int position) {

 를 통해서, 적절하게 viewpager를 관리해 주면, 실제 view가 반복해서 무한으로 반복되도록 보일수 있게 할 수 있다.


이번 포스트에서의 또다른 포인트는,
ViewPager 무한 반복 드래그 구현시, TextView, LinearLayout등의 컴포넌트 구현시에는 문제가 되지 않지만, ImageView의 경우, 다시 반복되는 View가 나타날때 Exception 발생으로 문제가 되었었던 내용이있다.
해결을 위해, ImageView사용대신, Linearlayout을 대신 사용하였고, 서버에서 ImageView로 이미지를 받은 이유로, 
Drawable drawable = mImageArray.get(position).getDrawable();
            linearlayout.setBackgroundDrawable(drawable);
와 같은 코드를 추가하였다.

그리고, 서버에서 받은 이미지가 view에 표시되기까지 시간이 걸리므로, 
handler를 사용하여 약간의 딜레이를 주도록 하였다.


소스코드는 아래와 같다.



1. res-layout-xml 파일

1
2
3
4
<android.support.v4.view.ViewPager
    android:id="@+id/product_viewpager"
       android:layout_width="260dp"
       android:layout_height="124dp"/>



2. src-java파일

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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
private ViewPager mProductPager;
 
 
public void init(ProductList plist) {
        mProductList = plist;
        mProductCnt = mProductList.getProductList().size();
        if(mProductCnt > 1) {
            mProductLeftArrow.setVisibility(View.VISIBLE);
            mProductRightArrow.setVisibility(View.VISIBLE);
        }
        
        mImageArray = new ArrayList<ImageView>();
        for(int i=0; i<mProductCnt; i++) {
            ImageView iv = new ImageView(mainActivity);
            //mainActivity.mResourceResolver.loadImage(new ImageHTTPGet(mProductList.getProductList().get(i).getIMAGE_URL()), iv);
            mImageArray.add(iv);
        }
 
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                ImagePagerAdapter pagerAdapter = new ImagePagerAdapter(mainActivity.getApplicationContext());
                mProductPager.setAdapter(pagerAdapter);
                mProductPager.setCurrentItem(mProductCnt);
                mProductPager.setOnPageChangeListener(new OnPageChangeListener() {
                    @Override public void onPageSelected(int position) {
                        if(position < mProductCnt){
                            //Logger.getInstance().log(TAG, "1 position+mProductCnt = " + (position+mProductCnt));
                            mProductPager.setCurrentItem(position+mProductCnt, false);
                        }
                        else if(position >= (mProductCnt*2)){
                            //Logger.getInstance().log(TAG, "2 position-mProductCnt = " + (position-mProductCnt));
                            mProductPager.setCurrentItem(position - mProductCnt, false);
                        }
                        else {
                            position -= mProductCnt;
                            mPrevPosition = position;
                            //Logger.getInstance().log(TAG, "3 mPrevPosition === " + mPrevPosition);
                        }
                        
                        mProductPage.setText(((position%mProductCnt)+1) + "/" + mProductCnt);
                    }
                    @Override public void onPageScrolled(int position, float positionOffest, int positionOffsetPixels) {}
                    @Override public void onPageScrollStateChanged(int state) {}
                });
                
                mPrevPosition = 0;
                int currNo = mPrevPosition + 1;
                mProductPage.setText(currNo + "/" + mProductCnt);
            }
        }, 500);
}
 
private class ImagePagerAdapter extends PagerAdapter{
        private Context mContext;
        public ImagePagerAdapter( Context con) { super(); mContext = con; }
 
        @Override public int getCount() { return (mProductCnt * 3); }
 
        @Override public Object instantiateItem(View pager, int position) 
        {
            position %= mProductCnt;
            final int pagerAdapterPosition = position;
 
            LinearLayout linearlayout = new LinearLayout(mContext);
            Drawable drawable = mImageArray.get(position).getDrawable();
            linearlayout.setBackgroundDrawable(drawable);
            Logger.getInstance().log(TAG, "1 pagerAdapterPosition = " + pagerAdapterPosition);
            
            linearlayout.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
//                    String uri = "http://m.amgbiz.firstmall.kr/goods/view?no=" + ;
                    //Logger.getInstance().log(TAG, "2 pagerAdapterPosition = " + pagerAdapterPosition);
                    //Logger.getInstance().log(TAG, "2 mProductList.getProductList().get(pagerAdapterPosition).getGOODS_LINK() = " + mProductList.getProductList().get(pagerAdapterPosition).getGOODS_LINK());
                    mainActivity.clickShopTab(mProductList.getProductList().get(pagerAdapterPosition).getGOODS_LINK());//pagerAdapterPosition 값이 보이는 이미지의 position보다 1이 더큼.
                }
            });
            
            ((ViewPager)pager).addView(linearlayout);
            return linearlayout;
        }
 
        @Override public void destroyItem(View pager, int position, Object view) {
            ((ViewPager)pager).removeView((View)view);
        }
 
        @Override public boolean isViewFromObject(View view, Object obj) { return view == obj; }
 
        @Override public void finishUpdate(View arg0) {}
        @Override public void restoreState(Parcelable arg0, ClassLoader arg1) {}
        @Override public Parcelable saveState() { return null; }
        @Override public void startUpdate(View arg0) {}
        @Override public int getItemPosition(Object object) {
            return POSITION_NONE;
        }
    }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
private ImageButton.OnClickListener onClick = new View.OnClickListener() {
        public void onClick(View v) {
            switch(v.getId()){
            case R.id.product_arrow_left:
                int pos = mProductPager.getCurrentItem();
                if(pos == 0 ) {
                    pos = mProductCnt - 1;
                } else {
                    pos --;
                }
                mProductPager.setCurrentItem(pos);
                break;
            case R.id.product_arrow_right:
                pos = mProductPager.getCurrentItem();
                if(pos == (mProductCnt - 1) ) {
                    pos = 0;
                } else {
                    pos ++;
                }
                mProductPager.setCurrentItem(pos);
                break;
                        }
        }
    };