출처 : http://www.androidpub.com/index.php?document_srl=1187851&act=trackback&key=169

<테스트한 코드>

1번> this.finish()

- AndroidManifest.xml 설정 필요 없음

2번> System.out(0)

- AndroidManifest.xml 설정 필요 없음

3번> android.os.Process.killProcess(android.os.Process.myPid());

- AndroidManifest.xml 설정 필요 없음

4번> ActivityManager am = (ActivityManager)activity.getSystemService(Activity.ACTIVITY_SERVICE);
am.restartPackage(activity.getPackageName());

- <uses-permission android:name="android.permission.RESTART_PACKAGES"/>

5번> ActivityManager am = (ActivityManager)activity.getSystemService(Activity.ACTIVITY_SERVICE);
am.killBackgroundProcesses(activity.getPackageName());

- <uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES"/>

<코드 설명>

1번 2번 3번은 테스트를 해본 결과 똑같은 종료방법이다.

하지만 종료되는 시점에 따라 종료가 될 수 있고 안될 수 있다.

ex1)

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

//여기서 1번 2번 3번은 절대 동작 안한다.

onstart에서도 마찬가지이다.

1번 2번 3번으로 종료시키기 위해서는 어떠한 이벤트나 동작이 이루어져야만 작동한다.

한마디로 종료시키는 시점이 중요하다.

ex2)

//A 액티비티

public class A extends Activity {

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

Intent intent = new Intent(this, B.class);
startActivity(intent);

//B 액티비티

public class B extends Activity {

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main2);

//여기서 1번 2번 3번은 절대 동작 안한다.

ex2의 예제는 ex1의 예제와 별다를 것이 없다.

하지만 만약 다른 액티비티를 불러와서 종료시킬 경우

1번 2번 3번을 B의 액티비티에서 쓰려하면 B의 액티비티만 종료된다.

자 그러면 B의 액티비티를 종료시켜보자.

ex3)

public class B extends Activity {

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main2);

Button myButton = (Button) findViewById(R.id.myButton);
myButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//1번 2번 3번으로 종료가 된다!!!!
}
});

ex3의 코드를 보면 B액티비티(2번째)만 종료가 된다. 클릭 이벤트를 발생시켰기 때문에

시점이란 것이 생겼다. 클릭 이벤트가 종료하게 도와준 것이다.

A의 액티비티도 똑같이 종료시키면 된다.

ex4)

public class A extends Activity {

private int a=1;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main2);

if(a==1){
//1번 2번 3번 종료가 된다.
}

ex4번 예제는 if문을 통하여 a변수를 확인하는 시점을 만들어줬다.

A는 종료가 된다.

이런식으로 종료하고 시키고 싶다면 boolean으로 하는것을 추천한다.

true와 false로 선택이 필요한 2가지이니 딱이고,

다른 여러 개발자가 볼때의 입장으로서도 확실하게 이해시키기 편하기 때문이다.

ex5)

//A액티비티

public class A extends Activity {

public static Activity activity; //<==주목하라

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

activity=this;

Intent intent = new Intent(this, B.class);
startActivity(intent);

//B액티비티

public class B extends Activity {

private boolean isB=true;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main2);

if(isB==true){

A.activity.finish(); //<==1번만 가능. A액티비티만 종료된다.

}

Button myButton = (Button) findViewById(R.id.myButton);
myButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {

//버튼 누르면 1번 2번 3번으로 B액티비티 종료시키기
}
});

ex5예제는 많은 분들이 질문하던 현재의 B액티비티안에서 뒤에 있는 액티비티

죽이는 방법이다. 1번만이 가능할 것이다.

1번 2번 3번으로 종료시켜 여러 어플을 만들다보면 분명 다 종료되고 위젯으로

나왔는데 남아있는 경우가 있다. 특히 Service를 extends 하여 사용하면 무조건

남는 경우가 있다.

남는지 안남는지 확인은 여러 방법이 있겠지만 간편한 마켓무료어플인

advanced task killer free를 써서 확인하고 있다.

이 어플은 어떤 어플이 백그라운드에서 살아있는지 이름을 가르켜준다.

이렇게 남아있으면 socket통신할 때 문제가 생기고(접속을 끊었는데 연결이 계속되있는 현상)

스마트폰에도 프로세스를 계속 읽고 있으니 별로 안좋을 것이다.

이럴 때 4번 5번을 쓰면 해결이 된다.

필자는 보통 마지막 종료되는 액티비티나 서비스의 ondestroy에 항상 써주고 있다.

4번은 2.1버전용(ver7)이고, 5번은 2.2버전용(ver8)이다.

그렇다면 매니패스트에서 <uses-sdk android:minSdkVersion="7" /> 에 따라

써야하나?

답은 NO다.

// 7버전 : <uses-permission android:name="android.permission.RESTART_PACKAGES"/>
// 8버전 : <uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES"/>

이 2개의 퍼미션은 같이 써도 무방하다.

그렇다면 4번과 5번의 차이점은 무엇인가?

일단 4번은 2.2버전(ver8)에서도 작동한다.

한마디로 4번만 써도 된다.

5번은 한가지 문제가 있다.

2.1버전 API에는 5번의 함수가 없다.

이클립스에서 new->new android project해서 만들때 Build Target 설정할 때의 버전차이에서 나타난다.

2.1버전으로할 경우 5번의 함수는 없다고 나온다.

5번을 쓸 수 있는 방법은 Build target를 2.2이상으로 바꾸면된다.

이클립스에서 default.properties를 열면 target=android-8로 바꾸면된다.

<uses-sdk android:minSdkVersion="8" /> 이 것도 쓸것이면 같은 8로 바꿔줘야한다.

(에러는 안 나지면 다르면 다르다고 표시는 날것이다.)

ex6)

public class A extends Activity {

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

//4번 5번은 여기서도 종료가 된다.

4번과 5번은 어떠한 시점에서도 종료가 된다. 한마디로 강제종료다!

저작자 표시 비영리 변경 금지
신고
블로그 이미지

프로그래머 지향자 RosaGigantea

바쁜 일상 생활중의 기억 장소

Jlet에서의 encodeImage 란 함수가 있습니다.

Graphics 밑에 딸려 나온 것으로 역할은 이미지 데이터를 byte [] 뽑아줍니다.
음... 사용법에 대해선 전에 주의점으로 소개를 했지만 다시 써봅니다.

public static Image CopyImage(Image src)
{
  // 지금 들어오는 src를 바로  그래픽 받아오게 하면, 읽기 전용상태라 NullPointException이 발생한다
  // 이를 방지하기위해 Image copy본을 만든뒤 그 이미지를 encodeImage 하면된다.

  byte []temp = null;
  Image copy = Image.createImage(src);
  Graphics g = copy.getGraphics();
 
  temp = g.encodeImage(0, 0, src.getWidth(), src.getHeight());
  Image result = Image.createImage(temp, 0, temp.length);
 
  return result;
 }

C언어와 달리 들어오는 Image src 에 대해서 바로 접근이 안됩니다.
C언어라면, 함수가 호출되면서 Image src의 복사본이 오게 되겠지만, Java 문법상.. (아니 Wipi만 그런가?)
C 언어로 치면 Image CopyImage(const Image &src) 와 같이 들어오는거 같습니다.

참 비효율적이라고 생각 됩니다. 아니.. 내공이 부족한건지.. 하여간 윗 소스는
1. 받아온 Image의 Copy 를 생성한다.
2. 그 복사본 이미지에 대한 그래픽을 만든다.
3. byte [] temp 라는 배열 안에 복사본 이미지 전체 영역, (0,0)~(width, height)만큼 인코딩 시킨다
4. 가져온 temp byte 배열을 가지고 이미지를 생성한다. 생성하되, 시작 번지는 0 ~ temp 길이 만큼임

으로 생각하시면 됩니다..


왜 이렇게 하는건지는 잘 모르겠지만. 뭐 wipi가 그러니 그려러니 하는 수밖에 없죠.. 왠지 알면 알수록
꼬인다는 느낌이 Wipi입니다.. orz

하여간 이 encodeImage 저는 이미지에 대해 변화를 많이 주는 프로세싱을 하다 보니,
일반적으로
1. GetPixel 로 좌표의 RGB 알아낸다.
2. 이 RGB를 적당한 알고리즘으로 변형시킨다.
3. SetColor 로 RGB값을 지정한다.
4. SetPixel로 해당 좌표에 점을 찍는다…

를 하기엔, 퍼포먼스가 너무 딸리게 됩니다. 돌아가는 환경이 PC로 치면 386,486급을 달리고 있고,
거기에 어셈만큼 빠른 C언어가 아닌 Java… 버추얼 PC를 통해서 느린 판국에 Class 개념의 객체 지향은
일반 C언어의 순차적 언어에 비하면 많이 느리죠
(모바일 경우.. 뭐 어떻게 뜯어 고쳐서 Jlet도 Clet에 비하면 80%정도 성능을 낸다고 합니다만.. 음…)

하여간, MFC의 (비교대상이 되려나..) GetPixel, SetPixel 를 사용하면 최신 듀얼 CPU 컴퓨터도 버벅이는 상황에서
모바일이라고 별수 있나요.. 그래서 GetPixel, SetPixel 을 사용하지 않고 이것을 배열에 다 넣은뒤
이 배열 값을 조작한 다음 다시 나중에 이미지 만들면 되겠다 싶어서 encodeImage에 대해 파게 됬습니다.. orz

우선 들어가기 앞서 Wipi Jlet API 에선 뭐라고 설명하는지 살펴 봅니다.

encodeImage
public byte[] encodeImage(int x, int y, int w, int h)

화면의 특정 영역을 BMP 포맷으로 인코딩한다. 인코딩된 BMP 포맷은 바이트 어레이로 반환되며 파일로 저장하거나 다시 이미지 생성에 이용할 수도 있다.

Parameters:
x - 인코딩할 영역의 시작 x 좌표
y - 인코딩할 영역의 시작 x 좌표
w - 인코딩할 영역의 폭
h - 인코딩할 영역의 폭

Returns:
인코딩된 BMP 포맷의 바이트어레이, 인코딩에 실패하면 null

Throws:
java.lang.IllegalArgumentException - 대상 영역의 일부가 Graphics의 범위를 벗 어나는 경우 또는 w, h가 음수인 경우

출처 : http://www.developerzone.co.kr/release/wipi/SKT_WIPI_JAVA2.0_API/org/kwis/msp/lcdui/Graphics.html#encodeImage(int,%20int,%20int,%20int)

음….. 화면 특정 영역을 BMP포멧으로 인코딩이라고 되있습니다.
여기서 햇갈리는게.. BMP포멧이 뭘까요?
BMP 포멧에 대해선 BMP 구조에 대해 알아야 하는데, 일반적인 BMP는 MS에서 만든 그거겠죠… 라고 생각하다가 조금 고생했습니다..
우선 BMP가 크게 header + (8bit 이하 그림이면) palettle +pixel data 로 구성 되있죠.

처음엔 그냥 BMP 포멧이라 하길래 BGR 값으로 byte 가 쫙~~~~~~~~~ 뽑힐줄 알았는데…
앞에 Header가 있더군요. Orz 일단 Header size 부터 알아냅시다..

System.out.println(src.getWidth()+"x" + src.getHeight() + "Imaghe bytes are " + temp.length);

System.out.println("pixel total number : " + src.getWidth()* src.getHeight());

System.out.println("header size : " + (temp.length - (src.getWidth() * src.getHeight()*3)));

System.out.println();

위 소스를 보면 이미지의 넓이, 높이에 대한 인코딩 추출 byte 길이가 나오고,
실제 이미지에 쓰인 픽셀이 몇 개인지 (해상도라고 하죠 보통..) 출력하고
header 사이즈에 대해 출력됩니다.

저기에 보면 temp 전체 길이에 대해서 픽셀 숫자의 3배수를 뺍니다.
여기서 혼동이 되는게 BMP 포맷은, 1픽셀을 4byte 로 표현합니다, AABBGGRR 로 구성되어있죠
하지만 Wipi 상 BMP 포맷은 RRGGBB 3byte 입니다.

가끔 MSDN 이 좋다고 느껴지는게, 조금 복잡하거나 생소한 API경우 예제 소스를 같이 포함해서 사용법에 대해 나와있는데
Wipi경우 이건 뭐 API만 쑥 던져주고 알아서 삽질하셈 인건지 뭔지… orz

하여간 저렇게 해서 header size를 알아냈으니 그 이후 픽셀부터 수정하면 될까요…?
정답은 꼭 그렇지는 않다 입니다..

허나 대부분은 저렇게 해서 나온 size 에서 + a 지점부터 x,y좌표 계산한 번지의 byte 숫자를 바꾸면 이미지 색이 바뀜니다.
alpha 값은… 저도 많이 삽질했지만 특별한 규칙이 있는건지 없는건지;;;
alpha 값은… header + 특정변수 의 변경값이 0,0의 픽셀을 변하는 곳이.. alpha값입니다.. (이 뭐 무책임한.. orz)
즉, 결론은... 저런거 삽질 할 시간에 차라리 int 같은 배열로 뽑아서 관리 하는게 훨~~~ 씬 편합니다.
int 로 어떻게 뽑냐면..
static int[] CraeteArrayImage(Image srcImg)
 {
      Image copyImg = Image.createImage(srcImg);
      Graphics g = copyImg.getGraphics();
   
      int[] arrayImg = new int[srcImg.getWidth()*srcImg.getHeight()];
 
      int bpp = 32;// getDisplay().getBitsPerPixel();
      int bpl = (srcImg.getWidth() * bpp + 7) / 8;
      g.getRGBPixels(0, 0, srcImg.getWidth(), srcImg.getHeight(), arrayImg, 0, bpl);
      return arrayImg;
 }
이렇게 해주시거나..
아니면...

static int[] CraeteArrayImage(Image srcImg)
 {
      Image copyImg = Image.createImage(srcImg);
      Graphics g = copyImg.getGraphics();
   
      int[] arrayImg = new int[srcImg.getWidth()*srcImg.getHeight()];
      int cnt = 0;
      for(int y=0; y < copyImg.getHeight(); ++y)
      {
           for(int x=0; x < copyImg.getWidth(); ++x)
          {
                 arrayImg[cnt++] = g.getPixel(x, y);
           }
       }
 
       return arrayImg;
 }
물론... int 는 4byte... 그림 RGB만 차지하는 byte는 3byte 이므로 불필요한 공간 25%가 더 쌓이는 코드입니다.
저걸 byte로 바꿔서 코딩하면.. 금방 될껍니다 ^^;

신고
블로그 이미지

프로그래머 지향자 RosaGigantea

바쁜 일상 생활중의 기억 장소

Java Advanced Imaging (JAI)

 

import javax.media.jai.*;



이 API를 이용하여 이미지 파일을 변경하거나 저장할 수 있다.

JAI 다운로드 페이지 : https://jai.dev.java.net/binary-builds.html

API : http://download.java.net/media/jai/javadoc/1.1.3/jai-apidocs/index.html


jai-1_1_3-lib.zip 파일 다운로드

압축 해제후 jar 파일들을 C:\j2sdk1.4.2_12\jre\lib\ext 로 복사

출처 : Tong - Popsicle님의 Java통

신고
블로그 이미지

프로그래머 지향자 RosaGigantea

바쁜 일상 생활중의 기억 장소

자바 소스를 컴파일한 class 파일을 디컴파일할 수 있는 툴은 여러가지가 있다.

개인적으론 Jad 라는 프로그램과 Decafe Pro 라는 프로그램을 즐겨 쓰는 편인데...

Decafe Pro 의 장점이라면 GUI 방식의 윈도우 지원 툴이라는 것이고

Jad 의 장점이라면 다양한 플랫폼을 지원하고

폴더내에 있는 모든 class 파일을 동시에 디컴파일 할 수 있다는 것이다.


여기서는 Jad의 간단한 사용법을 적어보겠다.

첨부된 파일은 Jad v1.5.8g 버전으로

class 파일들이 있는 폴더에 넣고


한 파일 디컴파일시에는 :

jad -sjava sample.class



폴더내 모든 class 파일 디컴파일시에는 :

jad -sjava *.class


하면 휘릭 하고 java 파일들이 생성된다.


Jad Homepage : http://www.kpdus.com/jad.html

신고
블로그 이미지

프로그래머 지향자 RosaGigantea

바쁜 일상 생활중의 기억 장소

자바에서 Random값을 구하는 방법으로는 크게 다음 두가지가 있다.

  1) java.lang.math.Random

  2) java.util.Random


이때 첫번째 방법은 seed값을 변환할 수 없기 때문에 고르게 분포하지 않는다.

그래서 seed값을 변환해 고른 난수추출을 할 수 있는 방법이 필요한데 이때,

두번째 방법을 사용한다. 아래의 예제는 아주 간단히 정규분포(Normal / Gaussian)에서

난수를 추출하는 방법을 보여주고 있다.

---------------------------------------------------------------------------------------

import java.util.Random;


public class RandomNumber {

    public static void main(String[] args) {
        Random rand = new Random(System.currentTimeMillis()); // seed값을 배정하여 생성
        System.out.println(Math.abs(rand.nextGaussian()));         // 난수값 출력

    }

}

----------------------------------------------------------------------------------------


아래의 예제는 다양한 범위에서 난수를 추출하는 방법을 보여주고 있다.

---------------------------------------------------------------------------------------

import java.util.Random;


public class RandomNumber {

    public static void main(String[] args) {
        Random rand = new Random(System.currentTimeMillis()); // seed값을 배정하여 생성
        System.out.println(Math.abs(rand.nextInt(10)));                //0~10사이의 난수값생성
        System.out.println(Math.abs(rand.nextInt(9)+1));               //1~10사이의 난수값생성
        System.out.println(Math.abs(rand.nextInt(990)+10));           //10-100사이의 난수값생성

    }

}

----------------------------------------------------------------------------------------

nextInt([숫자])를 사용할경우 0~[숫자]까지의 범위에서 난수가 추출되므로 예로 0~9까지 난수를

추출한후 1을 더해주면 1~10까지의 난수가 추출됨.



** 참고사항 : 컴퓨터상에서 난수추출과 Seed값 배정법(출처 : 네이버 지식검색 자료모음)


컴퓨터는 생각을 할 수 없습니다. 그래서 무작위로 수를 뽑는 것 역시 불가능합니다.
단, 엄청나게 긴 수열을 만들어 내어서 "난수"로 보이는 숫자를 만들어 낼 수 있는데
그것이 유사 난수(Pseudo random)이라고 합니다.
단, 이 수열의 집합은 Seed라는 지정번호에 좌우되는데(Seed가 같을 경우, random을

해도 같은 수열만 나온단 말이 되겠죠) Seed의 숫자에 따라서 생성되는 수열이 달라집니다.

프로그래머들은 Seed 번호를 대개 현재의 시각에 대응시킵니다. 그래서 한번의 Random

호출시마다 다른 난수가 생성됩니다. 즉 명령을 실행하라고 인간이 엔터키나 클릭을 한

시점의 시간을 1000분의 1초를 단위로 추출해서 그 수를 기본으로 난수를 만들기 때문에

언제나 실행 할때마다 전혀 다른 난수가 나오게 되는것입니다.


최종적으로는, seed를 and or xor 등등을 여러번 섞고 왼쪽 오른쪽으로 돌렸다가 비트단위로

반정도로 잘라서 뒤섞고 하는방식으로 만듭니다.

출처 : http://blog.naver.com/echris7/140012818525
이거 C언어랑 달라서.. (C언어는 int 리턴.. Java는 double 리턴..).. 쩝..

신고
블로그 이미지

프로그래머 지향자 RosaGigantea

바쁜 일상 생활중의 기억 장소

Tag Java