-1

I am developing a new app and but crashes when user logged in using email and password

below error from Logcat

android.view.WindowLeaked: Activity com.empowered.healo.ui.activities.main.MainActivity has leaked window DecorView@adb6956[MainActivity] that was originally added here
        at android.view.ViewRootImpl.<init>(ViewRootImpl.java:572)
        at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:331)
        at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:97)
        at android.app.Dialog.show(Dialog.java:419)
        at com.empowered.healo.mvp.BaseMvpActivity.showError(BaseMvpActivity.java:70)
        at com.empowered.healo.ui.activities.main.MainPresenter$getHelpTexts$2.accept(MainPresenter.kt:132)
        at com.empowered.healo.ui.activities.main.MainPresenter$getHelpTexts$2.accept(MainPresenter.kt:25)
        at io.reactivex.internal.observers.LambdaObserver.onError(LambdaObserver.java:74)
        at io.reactivex.internal.operators.observable.ObservableObserveOn$ObserveOnObserver.checkTerminated(ObservableObserveOn.java:276)
        at io.reactivex.internal.operators.observable.ObservableObserveOn$ObserveOnObserver.drainNormal(ObservableObserveOn.java:172)
        at io.reactivex.internal.operators.observable.ObservableObserveOn$ObserveOnObserver.run(ObservableObserveOn.java:252)
        at io.reactivex.android.schedulers.HandlerScheduler$ScheduledRunnable.run(HandlerScheduler.java:109)
        at android.os.Handler.handleCallback(Handler.java:751)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:154)
        at android.app.ActivityThread.main(ActivityThread.java:6682)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1520)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1410)

below my MainActivity.kt

     class MainActivity : BaseMvpActivity(), MainView {
         companion object {
             const val ACTION_FRAGMENT = "FRAGMENT_CHANGE"
             const val DELETE_THERAPY = "DELETE_THERAPY"
             const val CHANGE_PROFILE = "CHANGE_PROFILE"
             const val UPDATE_DATA = "UPDATE_DATA"
         }

         private var presenter = MainPresenter(this)
         private var navigator: Navigator? = null
         private var needUpdateData: Boolean = false
         private var pushData: Bundle = Bundle()
         private var needRedirect: Boolean = false
         private var fragmentReceiver: BroadcastReceiver? = null
         private var actionDrawerClose: (() - Unit)? = null
         private var firstScreen: String = Screen.HOME

         override fun onCreate(savedInstanceState: Bundle?) {
             super.onCreate(savedInstanceState)
             setContentView(R.layout.activity_main)
             handleInComeIntent()
             initNavigation()
             initData()
             initUI()
         }

         private fun initData() {
             presenter.subscribeToNotification()
             if (needUpdateData)
                 presenter.getSession(firstScreen)
             else moveToScreen(firstScreen, null)
             presenter.getHelpTexts()
         }

         private fun initNavigation() {
             navigator = getNavigator()
             (application as HealApplication).setNavigator(navigator)
         }

         private fun initUI() {
             Glide.with(this)
                     .load(R.drawable.splash)
                     .into(backgroundImage)

             initNavDrawer()
             val keyboardUtil = KeyboardUtil(this, drawerLayout.getChildAt(1))
             keyboardUtil.enable()
         }

         override fun onNewIntent(intent: Intent?) {
             super.onNewIntent(intent)
             this.intent = intent
             handleInComeIntent()
             if (needRedirect) {
                 needRedirect = false
                 (application as HealApplication).router.navigateTo(firstScreen, pushData)
             }
         }

         override fun onStart() {
             super.onStart()
             fragmentReceiver = object : BroadcastReceiver() {
                 override fun onReceive(context: Context?, intent: Intent?) {
                     when (intent?.action) {
                         ACTION_FRAGMENT - {
                             changeBackground()
                         }

                         DELETE_THERAPY - {
                             checkMenuState()
                         }

                         CHANGE_PROFILE - {
                             updateIcons()
                             navList.updateMenuItems()
                         }
                     }

                 }
             }
             val intentFilter = IntentFilter(ACTION_FRAGMENT)
             intentFilter.addAction(DELETE_THERAPY)
             intentFilter.addAction(CHANGE_PROFILE)
             fragmentReceiver?.let { LocalBroadcastManager.getInstance(this).registerReceiver(it,
 intentFilter) }

         }

         fun changeBackground() {
             val fragment = supportFragmentManager.findFragmentById(R.id.fragmentContainer)
             if (fragment != null && fragment is BaseMvpFragment && fragment.rootView != null) {
                 fragment.rootView.isDrawingCacheEnabled = true
                 (fragment as? HomeFragment)?.take()
                 fragment.rootView.buildDrawingCache(true)
                 val cache = fragment.rootView.getDrawingCache(true)
                 cache?.let {
                     if (backgroundImage.scaleType == ImageView.ScaleType.FIT_XY) {
                         backgroundImage.scaleType = ImageView.ScaleType.FIT_CENTER
                     }
                     backgroundImage.setImageDrawable(null)
                     val bitmap = Bitmap.createBitmap(cache)
                     backgroundImage.setImageBitmap(bitmap)
                 }
                 fragment.rootView.isDrawingCacheEnabled = false
             }
         }

         private fun updateIcons() {
             presenter.getGender()?.let {
                 when (it) {
                     User.Gender.MALE - navList.updateIconForMenuItem(R.string.item_menu_pain_profile,
 R.drawable.ic_icon_menu_pain_profile_man)
                     User.Gender.FEMALE - navList.updateIconForMenuItem(R.string.item_menu_pain_profile,
 R.drawable.ic_menu_pain_profile_woman)
                 }
             }

         }

         private fun checkMenuState() {
             navList.updateState(if (presenter.isFullMenu()) MenuView.MenuState.FULL else MenuView.MenuState.SHORT)
         }

         override fun onStop() {
             super.onStop()
             fragmentReceiver?.let { LocalBroadcastManager.getInstance(this).unregisterReceiver(it) }
         }

         private fun handleInComeIntent() {
             needRedirect = false
             intent?.let { intent -
                 needUpdateData = intent.getBooleanExtra(UPDATE_DATA, true)
                 //Local reminder
                 when (intent.getStringExtra(Notifications.PushData.ACTION)) {
                     Notifications.PushData.Reminder.OPEN_SESSION - {
                         pushData.putAll(intent.extras)
                         firstScreen = Screen.START_SESSION
                         needRedirect = true
                     }
                 }
                 //From server push notification
                 when (intent.getStringExtra(Notifications.PushData.HEAL_EVENT)?.substringAfterLast("\\"))
 {
                     Notifications.PushData.Message.MESSAGE_EVENT - {
                         firstScreen = Screen.CHAT
                         needRedirect = true
                     }
                     Notifications.PushData.Evaluation.EVALUATION_EVENT - {
                         pushData.putInt(Notifications.PushData.Evaluation.EVALUATION_ID,
 intent.getStringExtra(Notifications.PushData.Evaluation.EVALUATION_ID).toInt())
                         pushData.putString(Notifications.PushData.ACTION,
 Notifications.PushData.Evaluation.EVALUATION)
                         firstScreen = Screen.START_SESSION
                         needRedirect = true
                     }
                 }
                 intent?.extras?.clear()
                 val closeIntent = Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)
                 sendBroadcast(closeIntent)
                 toggleDrawerScreen(false)

             }
         }

         override fun handleNewDialogMessage() {
             val currentFragment = supportFragmentManager.findFragmentById(R.id.fragmentContainer)
             if (currentFragment !is ChatFragment) {
                 val badgeCount = navList.updateBadgeForMenuItem(R.string.support_feedback, 1)
                 Notifications.sendNotification(this,
                         Notifications.MessageNotification(this, Notifications.PushData.Message.LOCAL_PUSH_ID,
 badgeCount).createNotification(),
                         Notifications.PushData.Message.LOCAL_PUSH_ID)
             }
         }

         override fun setChatBadgeCount(count: Int) {
             navList.clearBadgeForMenuItem(R.string.support_feedback)
             navList.updateBadgeForMenuItem(R.string.support_feedback, count)
         }

         override fun startEvaluation(evaluationId: Int) {
             EvaluationDialog(evaluationId, activity = this).build()?.show()
         }

         private fun initNavDrawer() {
             closeDrawer.setOnClickListener { toggleDrawerScreen(false) }
             drawerLayout?.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED,
 Gravity.END)
             drawerLayout?.addDrawerListener(object : DrawerLayout.DrawerListener {
                 override fun onDrawerStateChanged(newState: Int) {

                 }

                 override fun onDrawerSlide(drawerView: View, slideOffset: Float) {

                 }

                 override fun onDrawerClosed(drawerView: View) {
                     actionDrawerClose?.invoke()
                 }

                 override fun onDrawerOpened(drawerView: View) {
                     actionDrawerClose = null
                 }


             })


             /*

             navList.setOnItemClickListener(object : ItemClickListener<MenuView.MenuItem {
             override fun onItemClicked(t: MenuView.MenuItem, position: Int) {
                 val fragment = Fragment()
                 val data = Bundle()
                 when (position) {
                     0 - {
                         fragment = NameOfYourFragment()
                     }

                     1 - {
                         fragment = NameOfYourFragment()
                     }

                     2 - {
                         fragment = NameOfYourFragment()
                     }

                     3 - {
                         fragment = NameOfYourFragment()
                     }

                     4 - {
                         fragment = NameOfYourFragment()
                     }

                     5 - {
                         fragment = NameOfYourFragment()
                     }

                     6 - {
                         fragment = NameOfYourFragment()
                     }
                     7 - {
                         toggleDrawerScreen(false)
                         presenter.logOut()
                         return
                     }
                     8 - {
                         navList.clearBadgeForMenuItem(R.string.support_feedback)
                         Notifications.cancelNotification(this@MainActivity,
 Notifications.PushData.Message.LOCAL_PUSH_ID)
                         fragment = NameOfYourFragment()
                     }

                     9 - {
                         data.putBoolean("profile", true)
                         fragment = NameOfYourFragment()
                     }
                     10 - {
                         fragment = NameOfYourFragment()
                     }
                     11 - {
                         data.putBoolean(AboutFragment.BACKGROUND_VIDEO, true)
                         fragment = NameOfYourFragment()
                     }
                     12 - {
                         fragment = NameOfYourFragment()
                     }
                     13 - {
                         fragment = NameOfYourFragment()
                         data.putBoolean(WebPageFragment.DIALOG, false)
                         data.putString(WebPageFragment.TOOLBAR_TITLE, getString(t.title))
                         data.putString(WebPageFragment.URL, BuildConfig.PRIVACY_POLICY)
                     }

                     14 -
                         fragment = NameOfYourFragment()

                     16 - fragment = NameOfYourFragment()

                     else - toggleDrawerScreen(false)

                 }
                 toggleDrawerScreen(false)


             }
         })

              */




             navList.setOnItemClickListener(object : ItemClickListener<MenuView.MenuItem {
                 override fun onItemClicked(t: MenuView.MenuItem, position: Int) {
                     val fragment = supportFragmentManager.findFragmentById(R.id.fragmentContainer)
                     var screen = ""
                     @Suppress("Annotator", "Annotator", "Annotator", "Annotator", "Annotator", "Annotator", "Annotator", "Annotator",
 "Annotator") val currentScreen =
 fragment!!.arguments?.getString(ScreenNavigator.SCREEN_NAME)
                     val data = Bundle()
                     when (t.title) {
                         R.string.item_menu_home - {
                             screen = Screen.HOME

                         }
                         R.string.item_menu_session - {
                             screen = Screen.START_SESSION
                         }

                         R.string.item_menu_pain_profile - {
                             screen = Screen.SELF_DIAGNOSIS
                         }
     // it crashed? lets try again.
                         R.string.item_menu_favourite - {
                             screen = Screen.FAVOURITE_EXERCISES
                         }

                         R.string.item_menu_progress_prognosis - {
                             screen = Screen.PROGRESS
                         }

                         R.string.item_menu_schedule_reminders - {
                             screen = Screen.SCHEDULE
                         }

                         R.string.item_menu_therapy_settings - {
                             screen = Screen.THERAPY_SETTINGS
                         }
                         R.string.sign_out - {
                             toggleDrawerScreen(false)
                             presenter.logOut()
                             return
                         }
                         R.string.support_feedback - {
                             navList.clearBadgeForMenuItem(R.string.support_feedback)
                             Notifications.cancelNotification(this@MainActivity,
 Notifications.PushData.Message.LOCAL_PUSH_ID)
                             screen = Screen.CHAT
                         }

                         R.string.item_menu_account - {
                             data.putBoolean("profile", true)
                             screen = Screen.PROFILE
                         }
                         R.string.therapy_information - {
                             screen = Screen.THERAPY_INFO
                         }
                         R.string.about_healo - {
                             data.putBoolean(AboutFragment.BACKGROUND_VIDEO, true)
                             screen = Screen.ABOUT
                         }
                         R.string.activity_journal - {
                             screen = Screen.ACTIVITY_JOURNAL
                         }
                         R.string.privacy_policy_title - {
                             screen = Screen.WEB_PAGE
                             data.putBoolean(WebPageFragment.DIALOG, false)
                             data.putString(WebPageFragment.TOOLBAR_TITLE, getString(t.title))
                             data.putString(WebPageFragment.URL, BuildConfig.PRIVACY_POLICY)
                         }

                         R.string.payment_settings -
                             screen = Screen.PAYMENT_SETTINGS

                         R.string.subscriptions - screen = Screen.SUBSCRIPTIONS

                         else - toggleDrawerScreen(false)

                     }
                     toggleDrawerScreen(false)

                     if (!screen.isEmpty() && screen != currentScreen) {
                         actionDrawerClose = if ((fragment is OnBackPressed) && (fragment.onBackPressed(screen, data))) {
                             null
                         } else {
                             { HealApplication.INSTANCE.router.navigateTo(screen, data) }
                         }
                     } else {
                         actionDrawerClose = null
                     }
                 }
             })
             navList.addItemDecoration(object : RecyclerView.ItemDecoration() {
                 override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
                     super.getItemOffsets(outRect, view, parent, state)
                     val position = parent.getChildAdapterPosition(view)
                     if (position == 0) {
                         outRect.top = 9.5f.dp
                     }
                 }
             })
             updateIcons()

             navList.layoutParams.width = getScreenWidth() / 2
             drawerListContainer.layoutParams.width = getScreenWidth() / 2
             drawerListContainer.invalidate()
             navList.requestLayout()
         }

         fun toggleDrawerScreen(open: Boolean) {
             if (open) {
                 hideKeyboard()
                 setDrawerAnimation()
                 drawerLayout?.openDrawer(Gravity.END)
             } else {
                 drawerLayout?.closeDrawer(Gravity.END, true)
             }

         }

         private fun setDrawerAnimation() {
             val animatorRecycler = ObjectAnimator.ofFloat(navList, View.TRANSLATION_X, 250f, 0f)
             animatorRecycler.duration = 500
             animatorRecycler.interpolator = LinearInterpolator()
             animatorRecycler.start()
         }

         private fun getScreenWidth(): Int {
             val display = windowManager.defaultDisplay
             val size = Point()
             display.getSize(size)
             return Math.max(size.x, size.y)
         }

         override fun onBackPressed() {
             val fragment = supportFragmentManager.findFragmentById(R.id.fragmentContainer)

             if (fragment is OnBackPressed) {
                 if (fragment.onBackPressed(null, null))
                     super.onBackPressed()
             } else {
                 if (drawerLayout.isDrawerOpen(Gravity.END)) {
                     drawerLayout.closeDrawer(Gravity.END, true)
                 } else {
                     super.onBackPressed()
                 }
             }
         }


     override fun moveToScreen(screen: String, data: Bundle?) {
         val bundle = Bundle()
         if (data != null)
             bundle.putAll(data)
         bundle.putAll(pushData)
         checkMenuState()
         if (needRedirect) {
             (application as HealApplication).router.newRootScreen(Screen.HOME, null)
             (application as HealApplication).router.navigateTo(screen, bundle)

         } else {
             (application as HealApplication).router.newRootScreen(screen, bundle)
         }
     }

     override fun onDestroy() {
         super.onDestroy()
         presenter.disconnectFromNotification()
     }

     private fun hideKeyboard() {
         KeyboardUtil.hideKeyboard(this)
     }

     override fun startGuide() {
         startActivityForResult(Intent(this, GuidanceActivity::class.java), GuidanceActivity.REQUEST_CODE)
     }

     override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
         super.onActivityResult(requestCode, resultCode, data)
         DiagnosticActivity.handleResult(data, requestCode, resultCode, (application as HealApplication).router)

         if (requestCode == GuidanceActivity.REQUEST_CODE) {
             moveToScreen(Screen.PROFILE, null)
         }
     }

     override fun onLogout() {
         finish()
         HealApplication.logout()
     }

     private fun getNavigator(): Navigator {
         return ScreenNavigator(this, R.id.fragmentContainer, Screen::class.java).navigator
     }

     override fun networkAvailable(isNetworkAvailable: Boolean) {

     }


 }

MainPresenter class

 class MainPresenter(var view: MainView) : BaseMvpPresenter() {

 private val exerciseRepository = SessionsRepository()
 private val reportDb = SessionReportDatabase()
 private val db = DiagnosticHistoryDatabase()
 private val dbTherapy = TherapyDatabaseV2()
 private val apiDiagnostic = DiagnosticNetwork()
 private val chatRepository = ChatRepository()
 private val usersNetwork = UsersNetwork()

 fun subscribeToNotification() {
     chatRepository.getUnreadMessageCount()
             .observeOn(AndroidSchedulers.mainThread())
             .subscribe({
                 view.setChatBadgeCount(it)
             }, Throwable::printStackTrace)

       val user = UsersDatabase.getCurrentUser()
      if (user == null)
         return

        SocketNetwork.instance.connect(SocketNetwork.instance.NOTIFICATION,user.id)
       val clazz = HashMap<String, Any()
       SocketNetwork.instance.addEvent(SocketNetwork.instance.NOTIFICATION +
  ":${user.id}", SocketNetwork.instance.NOTIFICATION, clazz.javaClass)
             .subscribeOn(Schedulers.io())
             .observeOn(AndroidSchedulers.mainThread())
             .subscribe({
                 Log.i("NOTIFICATION", it.toString())
                 when (it.getValue("event")) {
                     Notifications.PushData.Evaluation.EVALUATION_EVENT - {
                         val value = (it.getValue(Notifications.PushData.Evaluation.EVALUATION_ID) as
  Double).toInt()
                         view.startEvaluation(value)
                     }

                     Notifications.PushData.Message.MESSAGE_EVENT - {
                         view.handleNewDialogMessage()
                     }

                 }
             }, {
                 it.printStackTrace()
             })
 }

 fun disconnectFromNotification() {
     SocketNetwork.instance.closeSocket(SocketNetwork.instance.NOTIFICATION)
 }

 fun getSession(screen: String = Screen.HOME) {
     view.showLoading()
     exerciseRepository.getTherapyActive()
             .observeOn(AndroidSchedulers.mainThread())
             .subscribe({
                 view.hideLoading()
                 if (!it.isEmpty())
                     view.moveToScreen(screen, Bundle())
                 else checkLastDiagnostic()
             }, {
                 view.hideLoading()
                 it.printStackTrace()
                 view.moveToScreen(Screen.SELF_DIAGNOSIS, Bundle())
                 // logOut()
             })

     exerciseRepository.syncReports()
             .observeOn(AndroidSchedulers.mainThread())
             .flatMapIterable { it }
             .subscribe({
                 reportDb.updateSessionReport(it)
             }, Throwable::printStackTrace)


 }

 fun isFullMenu(): Boolean =
         dbTherapy.getAllTherapyCount()  0


 private fun checkLastDiagnostic() {
     view.showLoading()
     apiDiagnostic.getLastDiagnostic()
             .observeOn(AndroidSchedulers.mainThread())
             .switchIfEmpty {
                 view.hideLoading()
                 view.startGuide()
             }
             .subscribe({
                 view.hideLoading()
                 db.saveDiagnosticHistory(it)
                 val data = Bundle()
                 data.putBoolean("enable", false)
                 view.moveToScreen(Screen.SELF_DIAGNOSIS, data)
             }, {
                 view.hideLoading()
                 view.startGuide()
             })
 }

 fun logOut() {
     usersNetwork.logOut(UsersDatabase().getToken())
             .observeOn(AndroidSchedulers.mainThread())
             .subscribe({ view.onLogout() }, { view.showError(it.message) })
 }

 fun getHelpTexts() {
     usersNetwork.getHelpTexts(UsersDatabase().getToken())
             .observeOn(AndroidSchedulers.mainThread())
             .subscribe({ data - UsersDatabase().saveHelpText(data) }, { view.showError(it.message) })
 }

 fun getGender(): User.Gender? = UsersDatabase.getCurrentUser()?.getGender()

 }
Raghavendra
  • 2,305
  • 25
  • 30
  • why did you add `>` for all lines ? It difficult as hell to edit your question properly – Manohar Dec 28 '18 at 10:04
  • You are trying to show a dialog in BaseMvpActivity with a different context. But the context which u have used is already cleared. So pls check the context or activity is alive or not before showing the dialog. In native we use (!isFinishing()) use same conidition before showing the dialog – Raghavendra Dec 28 '18 at 10:04
  • @Raghavendra can you clarify what you are telling to me – Edgarjon Komilov Dec 28 '18 at 10:11
  • @EdgarjonKomilov can u post BaseMvpActivity class – Raghavendra Dec 28 '18 at 10:11
  • @Raghavendra can I share gist because I cant add more code to post – Edgarjon Komilov Dec 28 '18 at 10:14
  • @EdgarjonKomilov Just post Line no 65 to 70 of BaseMvpActivity.java which will have a method call as showError. – Raghavendra Dec 28 '18 at 10:15
  • @Raghavednrahttps://gist.github.com/kyodgorbek/619c67711c79af5f34046c7d0f06defd – Edgarjon Komilov Dec 28 '18 at 10:16
  • @Raghavednra I shared gist link https://gist.github.com/kyodgorbek/619c67711c79af5f34046c7d0f06defd please check it – Edgarjon Komilov Dec 28 '18 at 10:18
  • @Raghavendra Please check AlertDialog dialog = new CustomAlertDialogBuilder(this) .addMessage(errorMessage) .setPositiveButton("OK", DialogInterface::dismiss) .build(); try { if (dialog != null) { dialogs.add(dialog); dialog.show(); it – Edgarjon Komilov Dec 28 '18 at 10:19
  • Possible duplicate of [Activity has leaked window that was originally added](https://stackoverflow.com/questions/2850573/activity-has-leaked-window-that-was-originally-added) – Zoe Dec 28 '18 at 10:35

1 Answers1

-1

Can you try this,

I have added a check whether the activity is closing or not before showing the dialog. Along with the message accept the context as well and try.

@Override
    public void showError(Context context, String errorMessage) {
        if (errorMessage == null || errorMessage.trim().isEmpty())
            errorMessage = getString(R.string.default_error_message);
        AlertDialog dialog = new CustomAlertDialogBuilder(context)
                .addMessage(errorMessage)
                .setPositiveButton("OK", DialogInterface::dismiss)
                .build();
        try {
            if (dialog != null) {
                dialogs.add(dialog);

                //Added this line 

                if(!isFinishing()) 
                   dialog.show();
            }
        } catch (Exception e) {
            Crashlytics.logException(e);
        }
    }


@Override
    public void showError(Context context, int errorMessage) {
        showError(context, getString(errorMessage));
    }
Raghavendra
  • 2,305
  • 25
  • 30