[android] Activity idle timeout for HistoryRecord 에러 발생 시
Posted on 2011/04/29 01:38
SurfaceView를 상속한 뷰 클래스를 하나 만들어 액티비티를 띄울 경우 아래와 같은 에러가 발생하면서 뷰가 표시되지 않고, 까만 화면만 표시되다 에러가 발생하는 경우
WARN/ActivityManager(374): Launch timeout has expired, giving up wake lock! WARN/ActivityManager(374): Activity idle timeout for HistoryRecord{4776baf0 com.isulnara.game/.GameMain}
◆ 원인
-> SurfaceView를 상속한 뷰 내부의 쓰레드(Thread)에서 LOCK이 걸려서 발생함.
SurfaceView를 상속한 뷰 내부의 코드 중 아래처럼 synchronized를 사용하고
synchronized (holder) { ... }
액티비티 또는 쓰레드 내부에서 동시에 synchronized를 사용한 특정 메소드에 접근할 경우 LOCK이 걸려서 무한대기하다 에러를 발생시키는 것으로 확인했음..
◆ 해결방법
1. LOCK 발생 시키는 상황을 만들지 않도록 코딩 2. 동기화가 필요없을 경우 synchronized 블럭 제거
public class MainActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main);
/** * 스플래시 표시하는 것과 초기화를 동시에 진행시키기 위하여 쓰레드 처리 * */ private void initialize() { InitializationRunnable init = new InitializationRunnable(); new Thread(init).start(); }
/** * 초기화 작업 처리 * */ class InitializationRunnable implements Runnable { public void run() { // 여기서부터 초기화 작업 처리 // do_something } } }
SplashActivity.java
public class SplashActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.splash);
initialize(); }
private void initialize() { Handler handler = new Handler() { @Override public void handleMessage(Message msg) { finish(); // 액티비티 종료 } };
이렇게 하면 로딩 화면이 표시되는 동안에 특정 작업을 할 수 있습니다.
예를 들면 로딩에 시간이 걸리는 작업이 있을 경우 스플래시 화면이 표시되는 동안에 처리하는 거죠..
그리고, 또 다른 점은 시작 액티비티가 다르다는 것이죠..
로딩 화면 후 이동시키는 방식은 이동된 액티비티에서 뒤로 가기 버튼을 누르면 로딩 화면으로 돌아오게 되겠죠.. 이런 현상을 방지하려면 또 뭔가 작업을 해줘야 되겠구요..
질문있습니다 이 방법처럼 해서 잘되는데 문제는 어플을 종료후 다시 에뮬레이터로 마우스 클릭으로 실행을하니
Application is not installed on your phone 이렇게 뜨면서 실행이 안됩니다
근데 또 에뮬 다시켜서 자동실행 되도록 나두면 또 실행은 되구요 왜이런 현상이 생기나요...해결방법좀 알려주세요 ㅠㅠ
public class spl extends Activity{
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.spll);
Handler z = new Handler();
z.postDelayed(new splashhandler(), 5000);
}
class splashhandler implements Runnable{
public void run(){
startActivity(
new Intent(getApplication(),Main.class));
spl.this.finish();
}
}
}
이건 Main.java 소스입니다
package kr.ac.ys;
import android.app.Activity;
import android.content.Intent;
import android.graphics.drawable.AnimationDrawable;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
public class Main extends Activity {
AnimationDrawable frameAnimation;
public void onWindowFocusChanged(boolean hasFocus) {
if(hasFocus) frameAnimation.start();
}
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button b = (Button) findViewById(R.id.button3);
Button e = (Button) findViewById(R.id.button2);
Button f = (Button) findViewById(R.id.button1);
Button g = (Button) findViewById(R.id.button4);
Button h = (Button) findViewById(R.id.button5);
e.setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
Intent intent = new Intent(Main.this, help.class);
startActivity(intent);
overridePendingTransition(R.anim.fade, R.anim.hold);
finish();
}
});
f.setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
Intent intent = new Intent(Main.this, DB1.class);
startActivity(intent);
overridePendingTransition(R.anim.fade, R.anim.hold);
finish();
}
});
g.setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
Intent intent = new Intent(Main.this, sang.class);
startActivity(intent);
overridePendingTransition(R.anim.fade, R.anim.hold);
finish();
}
});
정확히 어떤 것을 원하시는지 모르겠네요..
일반적으로 특정 객체를 움직일 때는 Animation을 이용하면 편리합니다.
이동에는 TransitionAnimation 클래스를 이용하면 되겠네요.
Animation으로 원하는 것이 안될 경우에는 Canvas에 직접 그려야 되겠죠..
어렵다
2011/06/07 14:43
텍스트입력 창을 띄워서 거기에 값을 넣으면 디비에 저장하고 싶은데
텍스트 입력 창 띄우는 방법 좁 알려주세요!
간단한 입력 창은 AlertDialog에 EditText 하나 올리면 되구요.
AlertDialog.Builder alert = new AlertDialog.Builder(context);
alert.setView(editText);
AlertDialog로 검색해보세요. 많이 나옵니다.
좀 복잡하다면 그냥 Layout 구성해서 Activity 하나 만드는 게 좋겠죠..
ch
2011/07/05 23:57
시간걸리는 작업 처리하는 부분에서 오래걸리는 작업을 수행하면, 그 작업을 전부 수행할 때 까지 로딩화면을 안띄우다가, 다 끝나고 나서야 로딩화면을 띄우고, 3초 후에 메인화면을 띄우네요.... 또 화면을 돌리면 다시 로딩화면부터하구요.. 왜그런가요?
위에 설명을 수정하였습니다.
초기화 작업을 위해서는 쓰레드처리를 해야 됩니다.
처음 글 작성 시 이 부분을 언급하려다 귀찮아서 안했습니다.
화면 돌리면 다시 로딩되는 부분은 글 마지막 부분의 AndroidManifest.xml 부분을 다시 확인해보세요.
예제 프로젝트도 첨부하였습니다.
강식
2011/08/17 00:23
인트로띄우고나서 로그인띄우려고 합니다.
handleMessage부분에 fisnish()하고 startActivity(로그인)했거든요.
별 이상은 없는데, 인트로뜨고 로그인뜨기전에 바로 백버튼눌러서 종료했는데
2초후에 로그인이 뜨네요. 이러면안될것같은데요.
이처럼 액티비티들의 실행을 보통 어떻게 구현을 하나요?
안드로이드 기반에서 시리얼 통신에 관한 정보를 찾다 글을 보고 왔습니다만
잘 이해가 안되서 글 올립니다.
현재까지 수집한 정보로 안드로이드에서는 시리얼 통신이 안된다고 알고 있었는데 사용할수 있는 방법이 있으면
정보를 얻고 싶습니다.
무례한 부탁일지도 모릅니다만 안드로이드에서 시리얼 통신을 할수 있는 방법이 있으면 자세히좀 알고 싶습니다.
자바로 앱을 만드는 경우와 C나 Pascal 같은 언어로 개발하는 방법 등이 있습니다.
먼저 C나 Pascal 같은 언어로 개발하는 경우에는 일반적으로 PC에서 시리얼 통신 프로그램을 개발하는 것과 동일하며, 크로스 컴파일만 하면 됩니다. 에뮬레이터에서 테스트하기 위해서 장치만 /dev/ttyS2로 설정했습니다.
전 프리 파스칼로 개발했습니다.
자바로 앱을 만들 경우는 조금 복잡합니다. 기본 API에 시리얼통신 관련된 것이 없습니다. 그래서 NDK를 이용하여 C로 시리얼통신을 하는 라이브러리(*.so)를 만들고, 자바에서 JNI를 이용하여 그 라이브러리를 불러다 사용해야 됩니다.
저는 NDK를 이용하여 시리얼 포트를 제어하는 함수를 만들고 그 함수를 JNI를 이용하여 자바로 만든 앱에서 호출했습니다.(회사에서 안드로이드 기반 하드웨어를 개발하고 있는 중이라서 에뮬레이터에서만 동작됨을 확인했습니다)
구글에서 배포하는 NDK 예제 소스가 있으니 참고하시면 됩니다.
NDK나 JNI를 이용하지 않는 방법으로는 C나 Pascal 같은 언어로 시리얼 통신용 프로그램(데몬)을 만들고, TCP Server를 띄우고, 자바로 만든 앱에서 localhost TCP Server에 접속하여 데이터를 요청하면 C로 만든 프로그램(데몬)에서 시리얼포트를 통하여 데이터를 받고, 다시 앱으로 넘겨주는 방법도 있습니다.
C:\android\tools\emulator.exe -avd Android.2.0.1 -verbose -qemu -serial COM4
에러가 위 명령에서 발생하는지요?
먼저 하이퍼터미널 같은 프로그램으로 해당 COM 포트가 오픈되는지 먼저 확인해보세요..
위 명령을 내리기 전에 해당 포트를 오픈하고 있는 다른 프로그램이 있어서는 안되며, -avd 다음에 나오는 Android.2.0.1은 생성하신 Android Virtual Device 명으로 설정해야 됩니다.
저도 왜 에러가 발생되는지 모르겠네요..
Win이라면 관리자 권한으로 실행되었는지도 확인해보시고, 시리얼 포트도 한 번 변경해보세요.
그리고, 제가 블로그에 게시한 시리얼 통신 방법은 단독으로 동작되는 실행 프로그램 형식입니다.
혹시나 앱에서 시리얼 통신을 해야 된다면 위와 같은 방법으로 하는 것보다는 JNI를 이용하는 방법이 좋을 것입니다.