레이블이 프로그래밍인 게시물을 표시합니다. 모든 게시물 표시
레이블이 프로그래밍인 게시물을 표시합니다. 모든 게시물 표시

2013년 5월 26일 일요일

[Android] AsyncTask를 이용한 ProgressDialog 사용 예제

ProgressDialog 를 띄워서 현재 진행중인 작업의 진행률을 표시해보자.

싱글쓰레드를 사용하면 UI 갱신이 안되서 멀티쓰레드를 써야하는데

Thread를 직접 생성해서 사용할 수 있지만

AsyncTask 라는 쓰기 좋은 녀석이 있다는 사실.

아래는 공식 레퍼런스

http://developer.android.com/intl/ko/reference/android/os/AsyncTask.html

http://developer.android.com/intl/ko/reference/android/app/ProgressDialog.html


이번 예제는 버튼을 누르면 AsyncTask를 사용하여

ProgressDialog를 띄우고 진행 중인 작업 정보를 갱신해주면서

작업 종료시에 Dialog 닫고 Toast 메시지 하나 띄우는 예제임.

 
 

ProgressDlgTest.java
import android.app.ProgressDialog;
import android.content.Context;
import android.os.AsyncTask;
import android.widget.Toast;

public class ProgressDlgTest extends AsyncTask< Integer//excute()실행시 넘겨줄 데이터타입
            , String//진행정보 데이터 타입 publishProgress(), onProgressUpdate()의 인수 
            , Integer//doInBackground() 종료시 리턴될 데이터 타입 onPostExecute()의 인수
> {
 //ProgressDialog를 멤버로 하나 넣어줌
 private ProgressDialog mDlg;
 private Context mContext;
 
 public ProgressDlgTest(Context context) {
  mContext = context;
 }
 
 //onPreExecute 함수는 이름대로 excute()로 실행 시 doInBackground() 실행 전에 호출되는 함수
 //여기서 ProgressDialog 생성 및 기본 세팅하고 show()
 @Override
 protected void onPreExecute() {
  mDlg = new ProgressDialog(mContext);
  mDlg.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
  mDlg.setMessage("작업 시작");
  mDlg.show();
        
        super.onPreExecute();
    }

 //doInBackground 함수는 excute() 실행시  실행됨
 //여기서 인수로는 작업개수를 넘겨주었다.
 @Override
 protected Integer doInBackground(Integer... params) {
  
  final int taskCnt = params[0];
  //넘겨받은 작업개수를 ProgressDialog의 맥스값으로 세팅하기 위해 publishProgress()로 데이터를 넘겨준다.
  //publishProgress()로 넘기면 onProgressUpdate()함수가 실행된다.
  publishProgress("max", Integer.toString(taskCnt));
  
  //작업 진행, 여기선 넘겨준 작업개수 * 100 만큼 sleep() 걸어줌
  for (int i = 0; i < taskCnt; ++i) {
   try {
    Thread.sleep(100);
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
   //작업 진행 마다 진행률을 갱신하기 위해 진행된 개수와 설명을 publishProgress() 로 넘겨줌.
   publishProgress("progress", Integer.toString(i), "작업 번호 " + Integer.toString(i) + "번 수행중");
  }
  
  //작업이 끝나고 작업된 개수를 리턴 . onPostExecute()함수의 인수가 됨
  return taskCnt;
 }
 
 //onProgressUpdate() 함수는 publishProgress() 함수로 넘겨준 데이터들을 받아옴
 @Override
    protected void onProgressUpdate(String... progress) {
  if (progress[0].equals("progress")) {
   mDlg.setProgress(Integer.parseInt(progress[1]));
   mDlg.setMessage(progress[2]);
  }
  else if (progress[0].equals("max")) {
   mDlg.setMax(Integer.parseInt(progress[1]));
  }
    }
 
 //onPostExecute() 함수는 doInBackground() 함수가 종료되면 실행됨
  @Override
     protected void onPostExecute(Integer result) {
   mDlg.dismiss();
   Toast.makeText(mContext, Integer.toString(result)+ "개의 작업 완료", Toast.LENGTH_SHORT).show();
 }
}


Main.java
public class Main extends Activity {
    /** Called when the activity is first created. */
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        Button btn = (Button) findViewById(R.id.btn_popup);
        btn.setOnClickListener(new Button.OnClickListener() {
         public void onClick(View v) {
          //ProgressDlgTest 실행
          new ProgressDlgTest(Main.this).execute(100);
         }
        });
    }
}

AsyncTask 사용하면서 삽질을 좀 했는데

주의할 점이 많으니 사용 전 꼭 공식레퍼런스를 읽어보기.

첨엔 뭣 모르고 doInBackground() 함수내에서 ListView 갱신을 했더니 프로그램이 그냥 죽더라.

한참 헤매다가 AsyncTask 구조를 좀 이해하고 해결;;

결론은 UI 갱신은 publishProgress()를 사용해서 onProgressUpdate()콜백에서 처리해야 됨

암튼 직접 Thread 생성해서 작업하는거 보다 좋음




2013년 5월 23일 목요일

[Android] PopupWindow 사용 예제

팝업 윈도우를 사용해보자.

아래는 공식 레퍼런스

아래 처럼 버튼 클릭시 버튼 3개로 구성된 팝업윈도우를 띄워보자.


java 코드
public class Main extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        //팝업을 띄우기 위하 버튼 하나 만들고
        Button btn = (Button) findViewById(R.id.btn_popup);
        btn.setOnClickListener(new Button.OnClickListener() {
         public void onClick(View v) {
          
          //클릭시 팝업 윈도우 생성
          PopupWindow popup = new PopupWindow(v);
                LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
          //팝업으로 띄울 커스텀뷰를 설정하고
          View view = inflater.inflate(R.layout.test_popup_window, null);
          popup.setContentView(view); 
          //팝업의 크기 설정
          popup.setWindowLayoutMode(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
          //팝업 뷰 터치 되도록
          popup.setTouchable(true);
          //팝업 뷰 포커스도 주고
          popup.setFocusable(true);
          //팝업 뷰 이외에도 터치되게 (터치시 팝업 닫기 위한 코드)
          popup.setOutsideTouchable(true);
          popup.setBackgroundDrawable(new BitmapDrawable());
          //인자로 넘겨준 v 아래로 보여주기
          popup.showAsDropDown(v);
         }
        });
    }
}


test_popup_window.xml


    

xml 코드가 이상하게 붙네;;

암튼 이런식으로 커스텀 팝업윈도우를 쓸 수 있다.

2013년 5월 21일 화요일

[Android] Boradless 버튼 만들기

버튼을 생성하고 이미지를 안 입히면





















'새 계정 생성' 버튼 처럼 board 가 형성된다.

허나 이 board를 아래 그림 처럼 없애고 싶을때는


아래 속성을 넣어보자
android:background="?android:attr/selectableItemBackground"

그러면 아래 그림처럼 boardless 버튼이 완성



















2013년 5월 20일 월요일

[Android] root 경로 접근 및 파일 처리


루팅된 디바이스에서 다른 어플의 데이터를 접근해야 할 일이 생겨서

관련된 코드들을 좀 찾아봤는데

일단 국내 사이트에선 관련 자료가 정말 없더이다 ㅠ


일단 나의 목적은

root 경로의 파일 브라우징 및 파일 복사 처리였는데


처음엔 어리석게도 su 권한 얻은 상태에서

File 객체 열고 file.listfiles() 쓰면 root 경로 파일들도 다 볼 수 있을 줄 알았음 ㅋㅋㅋ

현실은 리턴 null이 날 반겨주네 ㅠ

몇 시간을 왜 null이 리턴되냐고!! 하며 삽질을 하다가

su 권한은 그렇게 쓰는게 아니라는걸 알게됨 ㅋㅋㅋㅋ 창피해라.


결론은 root 경로에선 File 객체 함수, FileInput/OutputStream 이딴거 못쓴다.

그럼 뭘 써야되냐

shell 명령어를 사용해야 함 (ls, cat)

관련해서 참고해야할 좋은 오픈 소스들이 있다.

- busybox 제작하신 분이 제공하는 roottools 라이브러리
https://code.google.com/p/roottools/

- ultra explorer 제작하신 분도 소스를 공개
https://github.com/kshark27/UltraExplorer

정말 고마우신 분들임.


이제 관련 코드를 간단히 살펴보자

BufferedReader reader = null;
try
{
 Process p = Runtime.getRuntime().exec("su");
 DataOutputStream os = new DataOutputStream(process.getOutputStream());
 reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
 os.writeBytes("명령어구문");
 os.flush();

 if(process.waitFor() != 0)
 {
  //
 }
 return reader;
}catch (IOException e)
{
}


뭐 대충 이런 식이다. (Ultra explorer 참고)

파일리스트를 얻고 싶으면 명령어구문에  ls 명령으로

결과값들을 BufferedReader에 담아 그걸 파싱해서 사용한다.

파일 복사는 'cat 파일 > 파일' 명령어를 사용한다. (cp는 busybox 없인 사용 못한다더라)

위 방법으로 다른 shell 명령들도 사용 가능.

자세한 내용은 오픈 소스를 참고하자.


[Android] Button 객체 활성/비활성

Button 객체를 활성/비활성 하는 함수를 알아보자.
Button button = new Button(context);

//활성화
button.setEnabled(true);
//비활성화
button.setEnabled(false);

//아래는 UI는 활성화 상태로 클릭 가능/불가능 설정임
//클릭 가능
button.setClickable(true);
//클릭 불가능
button.setClickable(false);



2013년 5월 18일 토요일

[Android] 슈퍼 유저 권한 얻기

어플에서

슈퍼 유저 권한을 얻어보자.
try {
 Runtime.getRuntime().exec("su");
}
catch(IOException e) {
 //이 경우는 루팅 안된 폰이란 소리
}

간단하군.