오류 : BinderProxy @ 45d459c0이 유효하지 않습니다. 활동이 진행 중입니까?
이 오류는 무엇입니까 ... 나는 stackoverflow 커뮤니티 에서이 오류에 대한 토론을 찾지 못했습니다. 자세한 :-
10-18 23:53:11.613: ERROR/AndroidRuntime(3197): Uncaught handler: thread main exiting due to uncaught exception
10-18 23:53:11.658: ERROR/AndroidRuntime(3197): android.view.WindowManager$BadTokenException: Unable to add window -- token android.os.BinderProxy@45d459c0 is not valid; is your activity running?
10-18 23:53:11.658: ERROR/AndroidRuntime(3197): at android.view.ViewRoot.setView(ViewRoot.java:468)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:177)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197): at android.view.Window$LocalWindowManager.addView(Window.java:424)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197): at android.app.Dialog.show(Dialog.java:239)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197): at com.vishal.contacte.Locationlistener$MyLocationListener.onLocationChanged(Locationlistener.java:86)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197): at android.location.LocationManager$ListenerTransport._handleMessage(LocationManager.java:179)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197): at android.location.LocationManager$ListenerTransport.access$000(LocationManager.java:112)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197): at android.location.LocationManager$ListenerTransport$1.handleMessage(LocationManager.java:128)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197): at android.os.Handler.dispatchMessage(Handler.java:99)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197): at android.os.Looper.loop(Looper.java:123)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197): at android.app.ActivityThread.main(ActivityThread.java:4363)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197): at java.lang.reflect.Method.invokeNative(Native Method)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197): at java.lang.reflect.Method.invoke(Method.java:521)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:862)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:620)
10-18 23:53:11.658: ERROR/AndroidRuntime(3197): at dalvik.system.NativeStart.main(Native Method)
이것은 활동이 파괴되는 동안 백그라운드 스레드를 실행 한 후 대화 상자를 표시하려고하기 때문에 발생했을 가능성이 큽니다.
대화 상자를 호출하는 활동이 대화 상자를 표시하려고 할 때 어떤 이유로 든 종료 될 때 일부 앱에서 때때로이 오류 가보고되었습니다. 나를 위해 그것을 해결 한 것은 다음과 같습니다.
if(!((Activity) context).isFinishing())
{
//show dialog
}
나는 이것을 사용하여 몇 년 동안 이전 버전의 Android 에서이 문제를 해결했으며 그 이후로 충돌을 보지 못했습니다.
나는 같은 문제에 직면하여 DiscDev가 제안한 코드 를 다음과 같이 약간 변경하여 사용했습니다.
if (!MainActivity.this.isFinishing()){
alertDialog.show();
}
countDownTimer
내 앱에 있을 때이 오류가 발생했습니다 . 내 앱에서 GameOver를 호출하는 메소드가
public void onFinish() {
GameOver();
}
그러나 실제로 사용자를 잘못 클릭하여 (클릭 게임) 시간이 끝나기 전에 게임이 종료 될 수 있습니다. 예를 들어 20 초 후에 게임 오버 대화 상자를 볼 countDownTimer
때 시간이 다되면 대화 상자가 다시 나타나지 않도록 취소하는 것을 잊었습니다 . 또는 어떤 이유로 위의 오류와 충돌했습니다.
대화 상자가 스레드로 인해이 문제를 해결하는 경우 UI 스레드에서 다음과 같이 실행해야합니다.
runOnUiThread(new Runnable() {
@Override
public void run() {
dialog.show();
}
});
이것에 대한 수정은 매우 간단합니다. 대화 상자를 표시하기 전에 활동이 마무리 단계를 거치고 있는지 테스트하십시오.
private Handler myHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case DISPLAY_DLG:
if (!isFinishing()) {
showDialog(MY_DIALOG);
}
break;
}
}
};
In my case, the problem was that Context
was kept as a weak reference in the class that extends Handler
. Then I was passing Messenger
, that wraps the handler, through an Intent
to a Service
. I was doing this each time the activity appeared on screen in onResume()
method.
So as you understand, Messenger was serialized together with its fields (including context), because it is the only way to pass objects using Intent
- to serialize them. At that moment when Messenger was passed to the service, the activity itself still wasn't ready for showing dialogs as it is in another state (being said onResume(), that is absolutely different from when the activity is already on the screen). So when messenger was deserialized, the context still was at the resuming state, while the activity actually was already on the screen. Moreover, deserialization allocates memory for new object, that is completely different from the original one.
The solution is just to bind to the service each time you need it and return a binder that has a method like 'setMessenger(Messenger messenger)' and call it, when you are binded to the service.
I solve this problem by using WeakReference<Activity>
as a context. The crash never appeared again. Here is a sample code in Kotlin:
Dialog manager class:
class DialogManager {
fun showAlertDialog(weakActivity: WeakReference<Activity>) {
val wActivity = weakActivity.get()
wActivity?.let {
val builder = AlertDialog.Builder(wActivity, R.style.MyDialogTheme)
val inflater = wActivity.layoutInflater
val dialogView = inflater.inflate(R.layout.alert_dialog_info, null)
builder.setView(dialogView)
// Set your dialog properties here. E.g. builder.setTitle("MyTitle")
builder.create().show()
}
}
}
And you show the dialog like this:
val dialogManager = DialogManager()
dialogManager.showAlertDialog(WeakReference<Activity>(this@MainActivity))
If you want to be super-duper protected from crashes. Instead of builder.create().show()
use:
val dialog = builder.create()
safeShow(weakActivity, dialog)
This is the safeShow
method:
private fun safeShow(weakActivity: WeakReference<Activity>, dialog: AlertDialog?) {
val wActivity = weakActivity.get()
if (null != dialog && null != wActivity) {
// Api >=17
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
if (!dialog.isShowing && !(wActivity).isFinishing && !wActivity.isDestroyed) {
try {
dialog.show()
} catch (e: Exception) {
//Log exception
}
}
} else {
// Api < 17. Unfortunately cannot check for isDestroyed()
if (!dialog.isShowing && !(wActivity).isFinishing) {
try {
dialog.show()
} catch (e: Exception) {
//Log exception
}
}
}
}
}
This is a similar method that you could use for safe dismissing the dialog:
private fun safeDismissAlertDialog(weakActivity: WeakReference<Activity>, dialog: AlertDialog?) {
val wActivity = weakActivity.get()
if (null != dialog && null != wActivity) {
// Api >=17
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
if (dialog.isShowing && !wActivity.isFinishing && !wActivity.isDestroyed) {
try {
dialog.dismiss()
} catch (e: Exception) {
//Log exception
}
}
} else {
// Api < 17. Unfortunately cannot check for isDestroyed()
if (!dialog.isShowing && !(wActivity).isFinishing) {
try {
dialog.dismiss()
} catch (e: Exception) {
//Log exception
}
}
}
}
}
This error occurs when you are showing the dialog for a context that no longer exists.
Before calling .show()
check that activity/context is not finishing
if (!(context instanceof Activity && ((Activity) context).isFinishing())) {
alert.show();
}
how about makes a new Instance of that dialog you want to call? I've actually just met the same problem, and that is what I do. so rather than :
if(!((Activity) context).isFinishing())
{
//show dialog
}
how about this?
YourDialog mDialog = new YourDialog();
mDialog1.show(((AppCompatActivity) mContext).getSupportFragmentManager(), "OrderbookDialog");
}
so rather than just checking is it safe or not to show the dialog, I think it's much more safe if we just create a new instance to show the dialog.
Like me, In my case I tried to create one instance (from a Fragment onCreate) and call the instance of those dialog in another content of adapterList and this will result in "is your activity running"- error. I thought that was because I just create one instance (from onCreate) and then it is get destroyed, so when I tried to call it from another adapterList I calling the dialog from old instance.
I am not sure if my solution is memory friendly or not, because I haven't tried to profile it, but it works (well surely, it is safe if you do not create too many instance)
'IT박스' 카테고리의 다른 글
“@ angular / core”에 의존하지 않는 것 같습니다. (0) | 2020.06.29 |
---|---|
nginx가 도메인 이름에 응답하는 이유는 무엇입니까? (0) | 2020.06.29 |
고착 된 / 사실적인 Resque 직원을 어떻게 정리합니까? (0) | 2020.06.29 |
개인 메소드를 호출하는 방법이 있습니까? (0) | 2020.06.29 |
Nexus 4에서 USB 디버깅 모드를 찾아서 켜는 방법 (0) | 2020.06.29 |