안드로이드 개발 질문/답변
(글 수 45,052)
MainActivity에서 SurfaceView를 상속받는 view를 하나 생성하여
view에서 게임 스레드를 돌리고 있습니다.
public class MainActivity extends Activity implements define{ private GameView mGameView = null; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mGameView = new GameView(this); setContentView(mGameView); } .......... }
GameView 생성 시 이미지 로드를 위한 이미지 로드 스레드를 생성 후
이미지 로드가 완료되면(로드 시 프로그레스 팝업 띄움) 게임 스레드가 돌아가도록 되어있습니다.
public GameView(Context context) { super(context); // 서피스에 변화가 생김을 감지하기 위해 사용자 서피스 등록 SurfaceHolder holder = getHolder(); // 서피스 메니저 핸들 holder.addCallback(this); mSurfaceHolder = holder; mContext = context; //백라이트 설정 관련 pm= (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); wl= pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "My Tag"); // 화면 잠금 상태 체크 - 슬립 후 복귀 시 잠금 화면일 때 스레드 제어용~ km = (KeyguardManager)mContext.getSystemService(Context.KEYGUARD_SERVICE); lgLogo = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.img_logo_lg); cyonLogo = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.img_logo_neocyon); // 이미지 로딩 스레드 ㄱㄱ / 로딩 완료시까지 게임 루프 스레드는 정지 createThreadAndDialog(); thread = new MingleThread(); // 게임 스레드 생성 initGame(); // 이 뷰가 포커스를 가지게 한다. setFocusable(true); // 터치모드일때도 키이벤트 사용 가능하도록(1.6 ver에선 이걸 안넣으면 back버튼 입력시 onKeyDown을 타고들어오질 않는다!!) setFocusableInTouchMode(true); }
//이미지랑 사운드 통합 로딩 public void createThreadAndDialog() { if(Language == KOR) dialog = ProgressDialog.show(mContext, "밍", "로딩중입니다. 잠시만 기다려주세요.", true); else dialog = ProgressDialog.show(mContext, "Ming", "Loading. Please wait...", true); Thread loadThread = new Thread(new Runnable() { int loadStep = 0; public void run() { initSounds(); while(loadImgProgress(loadStep)) // 이미지, 사운드 로드 { loadStep++; try { Thread.sleep(30); } catch (InterruptedException e) { e.printStackTrace(); } } handler.sendEmptyMessage(0); } }); loadThread.start(); } private Handler handler = new Handler() { public void handleMessage(Message msg) { dialog.dismiss(); dialog = null; isLoading = true; // 이미지 로딩 완료 체크 플레그 if(!isExit) // 이미지 로드 완료 후 게임 스레드 시작 { thread.setRunning(true); thread.start(); } } };
문제는 이미지 로딩(프로그레스 다이얼로그) 후 게임 스레드로 진입하면
인트로 화면이 뜨게 되는데 프로그레스 다이얼로그 화면에서부터 인트로 화면까지
키버튼을 계속 누르거나 화면 터치를 계속하면 인트로 화면이 넘어 간 후 타이틀 화면쪽에서
간혹 ANR 팝업이 뜹니다. ㅠㅠ
ANR 팝업은 응용프로그램이 사용자의 입력에 5초간 반응하지 않을때 띄우는걸로 알고 있는데요
저렇게 프로그레스 다이얼로그가 떠있는 상황이나 인트로 화면(로고 이미지가 나타났다 사라지는)같이
사용자 입력을 받아도 아무런 동작을 안해야 할때엔 시스템에 ANR 상황이 아니라는걸
어떻게 처리를 해야하는건가요??
ANR 팝업 때문에 환장하겠습니다. ㅠㅠ
이부분은 게임 메인 스레드 입니다.
class MingThread extends Thread{ @Override public void run() { while (mRun) { Canvas cv = null; long beforeTime = System.nanoTime(); try { if(_GamePause == 0) { cv = mSurfaceHolder.lockCanvas(null); // 백버퍼에 그린다 synchronized (mSurfaceHolder) { if(c == null) { c = cv; } gt_timer(); CheckTouch(); } } }finally{ if(cv != null) { mSurfaceHolder.unlockCanvasAndPost(cv); // 프론트 버퍼로 출력 } } sleepTime = mTimer-((System.nanoTime()-beforeTime)/1000000L); try { if(sleepTime>0){ Thread.sleep(sleepTime); } } catch (InterruptedException ex) { } } } public void setRunning(boolean b) { mRun = b; } }