펌 OK (출처 표시), 상업적 이용 NO, 컨텐츠 변경 NO



ListView Adapter 내부 getView 메소드에서 아래와 같은 방식 적용


public View getView(int position, View convertView, ViewGroup parent) {

.

.

.

HorizontalScrollView mScrollView = (HorizontalScrollView) convertView.findViewById(R.id.rf_horizon_scroll);

mScrollView.setOnTouchListener(new ScrollViewOnTouchListener(mScrollView, position));

.

.


}


private class ScrollViewOnTouchListener   implements View.OnTouchListener {

        HorizontalScrollView view;

        float historicX = Float.NaN;

        static final int DELTA_ON_CLICK = 30; // 이동 허용 범위

        long historicTime;

        int position;

        public ScrollViewOnTouchListener(HorizontalScrollView view, int position){

            this.view = view;

            this.position = position;

        }


        @Override

        public boolean onTouch(View v, MotionEvent event)

        {

            switch (event.getAction())

            {

                case MotionEvent.ACTION_DOWN:

    v.setBackgroundColor(Color.parseColor("#D5D5D5"));    // 터치된 리스트 아이템 색상 변경을 위한 코드

                    historicX = event.getX();

                    historicTime = System.currentTimeMillis();

                    break;


                case MotionEvent.ACTION_UP:

                    if (Math.abs(event.getX() - historicX) < DELTA_ON_CLICK) {

  // 아이템 터치시 작업할 내용

                    }

                    break;

                case MotionEvent.ACTION_CANCEL:

                    v.setBackgroundColor(Color.parseColor("#00000000"));   // UP or CANCEL 이벤트 발생 시 아이템 배경색 원상복구

                    break;

                default: return false;

            }

            return true;

        }

    }


설명 : 리스트뷰 내부에 스크롤뷰 영역은 리스트뷰의 아이템 터치이벤트가 발생하지 않는다.

          때문에 스크롤뷰에 클릭 리스너를 등록하여 최초 터지 지점(DOWN) 부터 UP 까지의 픽셀이 짧은 경우 스크롤링이 아닌

          단순 터치로 판단하고 그에 따른 이벤트를 실행하는 방법이다.

          경우에 따라 시간 필터를 추가로 적용 가능하다.



Android/View | Posted by 덩치 2016.03.07 16:56

Dialog 뒤의 뷰 터치 가능하게 하기

펌 OK (출처 표시), 상업적 이용 NO, 컨텐츠 변경 NO



mDialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);


추가


응용 : 구글맵에서 CustomDialog가 떠 있는 상태에서 다른 마커를 터치시 바로 마커 터치이벤트가 발생

          해당 옵션이 없는 상태에서 마커를 터치하면 Dialog Outside터치이벤트가 발생하고 마커 터치이벤트 발생 X



Android/WI-FI | Posted by 덩치 2015.08.31 14:55

소스코드로 WiFi 연결시키기

펌 OK (출처 표시), 상업적 이용 NO, 컨텐츠 변경 NO




WPA2 이외 보안방식에서도 작동하는지 테스트 안됨.

테스트 해보신분 댓글로 알려주시면 감사하겠습니다.


WifiConfiguration wifiConfig = new WifiConfiguration();

wifiConfig.SSID = String.format("\"%s\"", "ssid");

wifiConfig.preSharedKey = String.format("\"%s\"", "password");


WifiManager wifiManager = (WifiManager)getSystemService(WIFI_SERVICE);

int netId = wifiManager.addNetwork(wifiConfig);

wifiManager.disconnect();

wifiManager.enableNetwork(netId, true);

wifiManager.reconnect();




출처 : http://stackoverflow.com/questions/8818290/how-to-connect-to-a-specific-wifi-network-in-android-programmatically



Android/WI-FI | Posted by 덩치 2015.05.08 11:13

Wifi 비활성화일 때 스캔하는 방법

펌 OK (출처 표시), 상업적 이용 NO, 컨텐츠 변경 NO



일반적으로 많이 알려진 Wifi Scan 방법은 Wifi 활성화 돼 있을때만 가능하다.


때문에 Wifi Scan이 필요할 때, 사용자의 Wifi를 강제로 Enable 시킨 뒤 스캔을 하고, 스캔이 끝다면 다시 비활성화 시키는


방식으로 많이들 구현한다.


그런데 Android 버전 4.3(SDK 18)부터 추가된 '항상 검색 허용' 설정을 이용하면 Wifi비활성화 상태라


Wifi스캔할 수 있다.




해당 옵션이 활성화 돼 있을때만 위와같은 동작이 가능하다.


소스코드상으로는 해당 설정을 컨트롤 할 수 없으며, 사용자가 직접 설정할 수 있다.



따라서 SDK 버전이 18 이상인지, '항상 검색 허용' 설정이 활성화상태인지 체크를 한 다음


조건을 만족하지 않는다면 기존 방식을 이용하고, 만족한다면 Wifi를 건들지 않고 바로 스캔을 진행할 수 있다.



위 조건을 구현하는 방법은 아래와 같다.


if (Build.VERSION.SDK_INT >= 18) {  //  4.3 버전 이상인지 체크한다.

if (mWM.isScanAlwaysAvailable()) {  //  항상검색 허용 설정이 활성화상태인지 체크한다.

mWM.startScan();  // 바로 스캔 실행

return;

}

}

mWM.setWifiEnabled(true);

// 위 조건을 만족하지 않는다면 Wifi 상태에 변화를 줘서 BroadcastReceiver에 액션이 들어오게 하여 스캔을 진행한다.

// 자세한 방법은 http://biig.tistory.com/14 참조


끝.







펌 OK (출처 표시), 상업적 이용 NO, 컨텐츠 변경 NO



매니페스트에 설정된 어플의 버전을 가져오는 방법이다.


직접적으로 매니페스트의 버전을 가져올 수 없기때문에


패키지매니저를 통해 자기자신 패키지명을 대입하여


설치정보를 가져오는 방식이다.


public static String getPackageVersion(Context context) {

try {

PackageInfo pi = context.getPackageManager()

.getPackageInfo(context.getPackageName(),

PackageManager.GET_UNINSTALLED_PACKAGES);

return pi.versionName;

}

catch(Exception e) {

}

return new String("");

}


예를들어 매니페스트의 버전이 android:versionName="1.0.0" 이라면


1.0.0을 리턴한다.


버전체크가 필요할때 주로 사용되는 방법이다.



펌 OK (출처 표시), 상업적 이용 NO, 컨텐츠 변경 NO



웹뷰 내용을 롱클릭 하면 블럭설정이 된다.


기본적으로 롱클릭리스너에서 false를 리턴하기때문인데


아래와 같이 true로 수정하면 블럭지정이 되지 않는다.



mWebView.setOnLongClickListener(new OnLongClickListener() {

@Override

public boolean onLongClick(View v) {

return true;

}

});




펌 OK (출처 표시), 상업적 이용 NO, 컨텐츠 변경 NO


Error:Apostrophe not preceded by  에러는


string.xml 파일에서 어퍼스트로피(') 문자를 잘못 사용하는 경우 발생한다.

그중에서도 문자열 내용에 특수문자가 포함되어있을경우 나타나는데

간단하게 문자열 양 끝에 " 를 붙여주면 해결된다. 

예를 들면

<string name="dialog_message">'테스트용' 문자열입니다.</string>


이를


<string name="dialog_message">"'테스트용' 문자열입니다."</string>


이렇게 바꿔주면 된다.


물론 메시지를 출력해도 " 문자는 출력되지 않는다.


다른 해결방법으로는


어퍼스트로피 앞에 \를 붙여주는것이다. 예를들면


<string name="dialog_message">\'테스트용\' 문자열입니다.</string>




펌 OK (출처 표시), 상업적 이용 NO, 컨텐츠 변경 NO


이미지 크기를 절대값으로 주고 여러 단말에서 확인을 해 보면, 단말 해상도에 따라 이미지 크기가


제각각인 경우가 있다.


애초에 이미지를 선언할 때 xml에서 dp로 줘버리면 상관이 없겠지만(drawable 폴더에 제대로 분기했다는 가정 하에),


소스코드상에서 비트맵을 만들고, 그 이미지를 뿌리는 경우 참 애매하다.


이때 해상도별로 사이즈 설정을 통일되게 하는 방법에 대해 알아보자.


예를들어Height1280px인 단말기에서 알맞은 이미지 width28px, height28px 일 때,


이보다 높거나 낮은 해상도에서 그에 맞는 사이즈로 리사이징을 하기 위한 방법이다.


먼저 단말의 해상도를 구해야한다.


Drawable d = getResources().getDrawable(id);

DisplayMetrics displayMetrics = new DisplayMetrics();

getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);

float deviceHeight = displayMetrics.heightPixels;


이렇게하면 deviceHeight 에는 단말의 Height 사이즈가 리턴된다.

(어떤 단말에서는 1280, 어떤 단말에서는 2500몇 .. 이런식으로)


int dp = (int) (28 * (deviceHeight / 1280));


여기서 281280은 위에서 예시를 든것과 같이


1280px의 해상도 단말에서 알맞게 표시되는 이미지 크기 28px을 뜻한다.


이렇게 하면 단말 해상도가 커지거나 작아져도 dp값이 그에 따라 커지고 작아져서


모든 단말에서 알맞은 사이즈로 이미지가 표시된다.


디테일을 요구하는 작업에서는 다른 필터링이 추가되어야하겠지만, 일반적인범위 내에서는


위 방법을 이용하면 사이즈가 알맞게 잘 표시가 되었다.




펌 OK (출처 표시), 상업적 이용 NO, 컨텐츠 변경 NO


1.구버전 안드로이드 기본브라우저 (약 S5 이전단말의 기본브라우저)


try {

String[] proj = new String[] { Browser.BookmarkColumns.TITLE, Browser.BookmarkColumns.URL};

String sel = Browser.BookmarkColumns.BOOKMARK + " = 1"; // 0 = history, 1 = bookmark

Cursor mCur = getContentResolver().query(Browser.BOOKMARKS_URI, proj, sel, null, null);

mCur.moveToFirst();

String title = "";

String url = "";


if (mCur.moveToFirst() && mCur.getCount() > 0) {

boolean cont = true;

while (mCur.isAfterLast() == false && cont) {

title = mCur.getString(mCur.getColumnIndex(Browser.BookmarkColumns.TITLE));

url = mCur.getString(mCur.getColumnIndex(Browser.BookmarkColumns.URL));

mCur.moveToNext();

      }


}

}

catch (Exception e) {

}



2. 크롬 브라우저


try {

String[] proj = new String[] { Browser.BookmarkColumns.TITLE, Browser.BookmarkColumns.URL, Browser.BookmarkColumns.DATE };

Uri uriCustom = Uri.parse("content://com.android.browser/bookmarks");

String sel = Browser.BookmarkColumns.BOOKMARK + " = 1"; // 0 = history, 1 = bookmark

Cursor mCur = getContentResolver().query(uriCustom, proj, sel, null, null);

mCur.moveToFirst();

String title = "";

String url = "";


if (mCur.moveToFirst() && mCur.getCount() > 0) {

boolean cont = true;

while (mCur.isAfterLast() == false && cont) {

title = mCur.getString(mCur.getColumnIndex(Browser.BookmarkColumns.TITLE));

url = mCur.getString(mCur.getColumnIndex(Browser.BookmarkColumns.URL));


        }

mCur.moveToNext();

      }


}

}

catch (Exception e) {

}


3. 최신단말의 안드로이드 S브라우저 (약 S5이후 단말에서 많이 사용하는것같음)


try {

String[] proj = new String[] { Browser.BookmarkColumns.TITLE, Browser.BookmarkColumns.URL, Browser.BookmarkColumns.DATE };

Uri uriCustom = Uri.parse("content://com.sec.android.app.sbrowser.browser/bookmarks");

String sel = Browser.BookmarkColumns.BOOKMARK + " = 1"; // 0 = history, 1 = bookmark

Cursor mCur = getContentResolver().query(uriCustom, proj, sel, null, null);

mCur.moveToFirst();

String title = "";

String url = "";


if (mCur.moveToFirst() && mCur.getCount() > 0) {

boolean cont = true;

while (mCur.isAfterLast() == false && cont) {

if (!TextUtils.isEmpty(url)) {

title = mCur.getString(mCur.getColumnIndex(Browser.BookmarkColumns.TITLE));

url = mCur.getString(mCur.getColumnIndex(Browser.BookmarkColumns.URL));


}

mCur.moveToNext();

      }


}

}

catch (Exception e) {

}



Android/기본스킬 | Posted by 덩치 2014.11.17 17:19

전원버튼 이벤트 감지하기

펌 OK (출처 표시), 상업적 이용 NO, 컨텐츠 변경 NO


IntentFilter powerFilter = new IntentFilter(Intent.ACTION_SCREEN_OFF);

registerReceiver(mPowerBroadcast, powerFilter);



BroadcastReceiver mPowerBroadcast = new BroadcastReceiver() {

@Override

public void onReceive(Context context, Intent intent) {

if(Intent.getAction().equals("android.intent.action.SCREEN_OFF") {

// 스크린이 꺼질때 이벤트

}

else if(Intent.getAction().equals("android.intent.action.SCREEN_ON") {

// 스크린이 켜질때 이벤트

}

else

return;

}


}


그리고 onDestroy 등에서

unregisterReceiver(mPowerBroadcast);

를 이용해 브로드캐스트를 종료한다.