Android : ProgressDialog.show ()가 getApplicationContext와 충돌합니다.


109

왜 이런 일이 일어나는지 이해할 수없는 것 같습니다. 이 코드 :

mProgressDialog = ProgressDialog.show(this, "", getString(R.string.loading), true);

잘 작동합니다. 그러나이 코드 :

mProgressDialog = ProgressDialog.show(getApplicationContext(), "", getString(R.string.loading), true);

다음 예외가 발생합니다.

W/WindowManager(  569): Attempted to add window with non-application token WindowToken{438bee58 token=null}.  Aborting.
D/AndroidRuntime( 2049): Shutting down VM
W/dalvikvm( 2049): threadid=3: thread exiting with uncaught exception (group=0x4001aa28)
E/AndroidRuntime( 2049): Uncaught handler: thread main exiting due to uncaught exception
E/AndroidRuntime( 2049): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.tastekid.TasteKid/com.tastekid.TasteKid.YouTube}: android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application
E/AndroidRuntime( 2049):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2401)
E/AndroidRuntime( 2049):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2417)
E/AndroidRuntime( 2049):    at android.app.ActivityThread.access$2100(ActivityThread.java:116)
E/AndroidRuntime( 2049):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1794)
E/AndroidRuntime( 2049):    at android.os.Handler.dispatchMessage(Handler.java:99)
E/AndroidRuntime( 2049):    at android.os.Looper.loop(Looper.java:123)
E/AndroidRuntime( 2049):    at android.app.ActivityThread.main(ActivityThread.java:4203)
E/AndroidRuntime( 2049):    at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime( 2049):    at java.lang.reflect.Method.invoke(Method.java:521)
E/AndroidRuntime( 2049):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:791)
E/AndroidRuntime( 2049):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:549)
E/AndroidRuntime( 2049):    at dalvik.system.NativeStart.main(Native Method)
E/AndroidRuntime( 2049): Caused by: android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application
E/AndroidRuntime( 2049):    at android.view.ViewRoot.setView(ViewRoot.java:460)
E/AndroidRuntime( 2049):    at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:177)
E/AndroidRuntime( 2049):    at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91)
E/AndroidRuntime( 2049):    at android.app.Dialog.show(Dialog.java:238)
E/AndroidRuntime( 2049):    at android.app.ProgressDialog.show(ProgressDialog.java:107)
E/AndroidRuntime( 2049):    at android.app.ProgressDialog.show(ProgressDialog.java:90)
E/AndroidRuntime( 2049):    at com.tastekid.TasteKid.YouTube.onCreate(YouTube.java:45)
E/AndroidRuntime( 2049):    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1123)
E/AndroidRuntime( 2049):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2364)
E/AndroidRuntime( 2049):    ... 11 more

왜 이런 일이 발생하는지 아이디어가 있습니까? 나는 이것을 onCreate메소드 에서 호출하고 있습니다 .


을 사용하는 Fragment경우 stackoverflow.com/questions/24825114/…
— Yeo

답변:


42

어떤 API 버전을 사용하고 있습니까? 문제가 옳다면 Android 1.6 (API 버전 4)에서 수정되었습니다.

getApplicationContext()null을 가리키는 객체 참조처럼 보입니다 . onCreate()윈도우가 실제로 빌드되기 전에의 일부 코드 가 실행되고 있다는 점에서 내가 가진 것과 비슷한 문제가 있다고 생각합니다 . 이것은 해킹이 될 것이지만 몇 백 밀리 초 안에 새 스레드를 시작해보십시오 (IIRC : 300-400이 저에게 적합한 것처럼 보였지만 수정해야 함) ProgressDialog를 열고 필요한 모든 것을 시작합니다 ( 예 : 네트워크 IO). 이 같은:

@Override
public void onCreate(Bundle savedInstanceState) {
    // do all your other stuff here

    new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
            mProgressDialog = ProgressDialog.show(
               YouTube.this.getApplicationContext(), "",
               YouTube.this.getString(R.string.loading), true);

            // start time consuming background process here
        }
    }, 1000); // starting it in 1 second
}

6
1.6을 사용하고 있습니다. UI 작업은 UI 스레드에서 수행해야하므로 별도의 스레드에서 ProgressDialog.show ()를 호출하는 것이 큰 문제가 될 수 있습니다. 아직도 이것이 이상하다고 생각합니다.
— Felix

3
내가 준 예제에서 다른 스레드에서 UI 작업을 수행하지 않고 다른 스레드는 UI 스레드를 다시 호출하여 대화 상자를 열도록 지시합니다.
— Jeremy Logan

확실히 이상하고 완전한 해킹이지만 나를 위해 일했습니다. 1.6에서 가지고 있던 버그를 테스트하여이 사용을 중지 할 수 있는지 확인해야합니다.
— Jeremy Logan

1
'이상한'것도 아니고 '완전한 해킹'도 아닙니다. 완벽하게 합법적 인 접근 방식입니다!
— KomodoDave

1
@KomodoDave 나는 방금 동일한 문제가 있음을 깨달았습니다. 그러나 나쁜 해킹은 타이머에 있습니다. 이것은 일부 상황에서 간헐적으로 실패하기를 기다리는 타이밍 창입니다. 성공의 열쇠는 더 짧은 타이머를 설정하고, 응용 프로그램이 준비되었는지 확인하고, 준비가 될 때까지 작업을 다시 배치하는 것입니다. 시도 할 횟수도 제한 할 것입니다.
— Jim Rush

129

API 레벨 7과 함께 Android 버전 2.1을 사용하고 있습니다.이 (또는 유사한) 문제에 직면하여 다음을 사용하여 해결했습니다.

Dialog dialog = new Dialog(this);

대신 :

Dialog dialog = new Dialog(getApplicationContext());

도움이 되었기를 바랍니다 :)


4
비슷한 문제가 있었지만 ActivityGroup을 사용하고있었습니다. 이 오류를 해결할 수있는 유일한 방법은 대신 getParent ()를 사용하는 것입니다.
— brack

20
이것이 그의 질문에 어떻게 대답합니까? 그는 왜 두 번째는 작동하지 않는 반면 첫 번째는 작동하는지 묻습니다.
— Burkhard 2011-06-29

3
-1, 'this'는 우리 중 일부에게 'getApplicationContext ()'와 동일합니다.
— kellogs

2.1 개발에 유용한 팁
— Carlos P

64

나를 위해 일하는 변화

builder = new AlertDialog.Builder(getApplicationContext());

에

builder = new AlertDialog.Builder(ThisActivityClassName.this);

이상한 점은 첫 번째는 Google 튜토리얼에서 찾을 수 있고 사람들은 이것에 대해 오류가 발생한다는 것입니다.


1
onclick 이벤트 내부 경고와 함께 작동하는 유일한 솔루션
— Tobias

이것이 올바른 방법입니다. 꼭 필요한 경우가 아니면 ApplicationContext를 사용하지 말고, 무엇보다도 UI 요소를 표시하는 데 사용하지 마십시오. 이것이 바로 활동 (그리고 궁극적으로 조각)의 목적입니다.
— Martin Marconcini 2013 년

이것은 하나입니다. this예를 들어 클릭 리스너 내에서 수행하는 경우 단독으로 작동하지 않습니다.
— 아이 만 살라

23

이것이 null 응용 프로그램 컨텍스트와 관련된 타이밍 문제라고 생각하지 않습니다.

앱 내에서 애플리케이션을 확장 해보십시오 (또는 이미있는 경우 사용하십시오).

public class MyApp extends Application

인스턴스를 비공개 싱글 톤으로 사용할 수 있도록합니다. 이것은 null 이 아닙니다.

private static MyApp appInstance;

MyApp에서 정적 도우미 만들기 (싱글 톤 사용)

    public static void showProgressDialog( CharSequence title, CharSequence message )
{
    prog = ProgressDialog.show(appInstance, title, message, true); // Never Do This!
}

팔!!

또한 여기에서 Android 엔지니어의 답변을 확인하십시오 : WindowManager $ BadTokenException

이 오류의 한 가지 원인은 활동이 아닌 컨텍스트를 통해 응용 프로그램 창 / 대화 상자를 표시하려고 할 수 있습니다.

자, 동의합니다. 메서드가 Activity 대신 Context 매개 변수를 사용한다는 것은 의미가 없습니다.


10

위의 답변을 읽은 후 내 상황에 따라 다음 문제가 해결되었음을 알았습니다.

이로 인해 오류가 발생했습니다.

myButton.setOnClickListener(new OnClickListener(){
    public void onClick(View v) {
        MyDialogue dialog = new MyDialogue(getApplicationContext());
        dialog.show();              
    }
});

컨텍스트가 잘못되었음을 제안한 이전 답변을 기반으로 버튼 onClick 메서드에 전달 된 View에서 컨텍스트를 검색하도록 getApplicationContext ()를 변경했습니다.

myButton.setOnClickListener(new OnClickListener(){
    public void onClick(View v) {
        MyDialogue dialog = new MyDialogue(v.getContext());
        dialog.show();              
    }
});

나는 자바의 작동을 완전히 이해하지 못해서 내가 틀릴 수 있지만, 내 특정 상황에서 원인은 위의 스 니펫이 추상 활동 클래스에 정의되었다는 사실과 관련이있을 수 있다고 생각합니다. 많은 활동에서 상속되고 사용됩니다. 아마도 getApplicationContext ()가 유효한 컨텍스트를 반환하지 않는다는 사실에 기여했을 수 있습니까 ?? (그냥 추측).


점수가 더 높은 솔루션이 대부분의 경우에 작동하지만 v.getContext () 기술은 저와 같이 가장 완고한 경우를 해결하는 것 같습니다. 경험적 자바 지식은 onCreated 메소드에서 오는 컨텍스트가 onClick 메소드의 View에서 오는 컨텍스트와 정확히 동일하지 않다고 생각하게합니다. 투표하세요!
— 조쉬

이것은 내 하루를 구했습니다!
— Alejandro Luengo

6

항목 별 오버레이가있는지도보기를 만들고 있습니다. 내 mapActivity에서 다음과 같이 itemizedoverlay를 만들었습니다.

OCItemizedOverlay currentLocationOverlay = new OCItemizedOverlay(pin,getApplicationContext);

내 itemizedoverlay의 onTap 메서드가 트리거 될 때 (위치가 mapview에서 탭될 때) "android.view.WindowManager $ BadTokenException : Unable to add window-token null is not for an application"예외가 발생한다는 것을 발견했습니다.

생성자에 'getApplicationContext ()'대신 'this'를 전달하면 문제가 해결된다는 것을 알았습니다. 이것은 alienjazzcat의 결론을 뒷받침하는 것 같습니다. 기묘한.


1
감사합니다. 이것이 바로 제 문제였습니다.
— Kon

4

TabActivities에 표시된 활동의 경우 getParent ()를 사용하십시오.

final AlertDialog.Builder builder = new AlertDialog.Builder(getParent());

대신에

final AlertDialog.Builder builder = new AlertDialog.Builder(this);

3

Android 2.2의 경우
다음 코드를 사용하십시오.

//activity is an instance of a class which extends android.app.Activity
Dialog dialog = new Dialog(activity);

이 코드 대신 :

// this code produces an ERROR:
//android.view.WindowManager$BadTokenException: 
//Unable to add window -- token null is not for an application
Context mContext = activity.getApplicationContext();
Dialog dialog = new Dialog(mContext);

비고 : 내 사용자 지정 대화 상자는 activity.onCreateDialog(int dialogId)메서드 외부에서 생성 됩니다.


3

시도-

AlertDialog.Builder builder = new AlertDialog.Builder(getParent());

현재 활동이 활동 그룹 내부에있을 때 필요
— htafoya 2011

2

getActivity()내부 를 사용하는 (호환성) 조각과 비슷한 문제가있었습니다.ProgressDialog.show() 충돌 가있었습니다. 타이밍 때문이라는 데 동의합니다.

가능한 수정 :

mContext = getApplicationContext();

if (mContext != null) {
    mProgressDialog = ProgressDialog.show(mContext, "", getString(R.string.loading), true);
}

사용하는 대신

mProgressDialog = ProgressDialog.show(getApplicationContext(), "", getString(R.string.loading), true);

mContext를 가능한 한 빨리 배치하여 컨텍스트를 확보하는 데 더 많은 시간을 제공하십시오. 여전히 이것이 작동 할 것이라는 보장은 없으며 충돌 가능성을 줄입니다. 그래도 작동하지 않으면 타이머 해킹에 의존해야합니다 (나중에 대화 상자를 닫는 것과 같은 다른 타이밍 문제를 일으킬 수 있음).

당신이 사용할 수있는 경우 물론, this또는 ActivityName.this때문에, 그것은 더 안정적입니다 this이미 뭔가를 가리 킵니다. 그러나 특정 Fragment 아키텍처와 같은 경우에는 옵션이 아닙니다.



2

활동 내에서 대화 상자를 사용하려면 다음과 같이하십시오.

private Context mContext;
private AlertDialog.Builder mBuilder;

@Override
protected void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
     mContext = this;

     //using mContext here refering to activity context
     mBuilder = new AlertDialog.Builder(mContext);
     //...
     //rest of the code
     //...
}

조각 내에서 대화 상자를 사용하려면 다음과 같이하십시오.

private Context mContext;
private AlertDialog.Builder mBuilder;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
      View mRootView = inflater.inflate(R.layout.fragment_layout, container, false);
      mContext = getActivity();

      //using mContext here refering to fragment's hosting activity context
      mBuilder = new AlertDialog.Builder(mContext);
      //...
      //rest of the code
      //...
      return mRootView;
}

그게 다야 ^ _ ^


1

이 문제를 해결하기 위해 내가 한 것은 글로벌 데이터를 저장하는 모든 활동에 대한 기본 클래스를 만드는 것이 었습니다. 첫 번째 활동에서 다음과 같이 기본 클래스의 변수에 컨텍스트를 저장했습니다.

기본 클래스

public static Context myucontext; 

기본 클래스에서 파생 된 첫 번째 활동

mycontext = this

그런 다음 대화 상자를 만들 때 getApplicationContext 대신 mycontext를 사용합니다.

AlertDialog alertDialog = new AlertDialog.Builder(mycontext).create();

이 솔루션이 더 이상 찬성표를 얻지 못해 부끄럽습니다. 가능한 솔루션은 여기에 제시된 모든 중,이는 AsyncTask를 나를 위해 일한 유일한 일
— CKn을

1

조각에서 ProgressDialog.show ()를 호출하는 경우 mContext를 Activity로 캐스팅하면 저에게 효과적이었습니다.

     ProgressDialog pd = new ProgressDialog((Activity) mContext);

1

이것은 일반적인 문제입니다. this대신 사용하면 getApplicationContext() 문제가 해결됩니다.


0

현재 activitty 뷰에 예외를 던지는 경고 대화 상자를 구현했습니다.

AlertDialog.Builder builder = new AlertDialog.Builder(context);

사용에서 onCreate (). 그래서 간단한 I에서 경고에 대한 같은 창 특례를 쓰기 코드를 감안할 때 context = this;이후 setContentView()에 문 onCreate()같은 글로벌로 method.Taken 컨텍스트 변수Context context;

코드 샘플은

static Context context;

 public void onCreate(Bundle savedInstanceState)  { 
        super.onCreate(savedInstanceState); 


        setContentView(R.layout.network); 
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

        context = this;
.......

경고 방법 샘플은

private void alertException(String execMsg){
        Log.i(TAG,"in alertException()..."+context);
        Log.e(TAG,"Exception :"+execMsg);
        AlertDialog.Builder builder = new AlertDialog.Builder(context);
.......

그것은 나를 위해 잘 작동합니다. 실제로 StackOverflow 에서이 오류를 검색했습니다.이 쿼리를 찾았습니다.이 게시물의 모든 응답을 읽은 후이 방법을 시도했기 때문에 작동합니다.이 예외를 극복하기위한 간단한 해결책이라고 생각했습니다.

감사합니다, Rajendar


0

groupActivity에 문제가 있으면 이것을 사용하지 마십시오. PARENT는 Parent ActivityGroup의 정적입니다.

final AlertDialog.Builder builder = new AlertDialog.Builder(GroupActivityParent.PARENT);

대신에

final AlertDialog.Builder builder = new AlertDialog.Builder(getParent());

당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.