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.