Unable to add window -- token android.os.BinderProxy is not valid; is your activity running?
This can occur when you are showing the dialog for a context that no longer exists. A common case - if the 'show dialog' operation is after an asynchronous operation, and during that operation the original activity (that is to be the parent of your dialog) is destroyed. For a good description, see this blog post and comments:
http://dimitar.me/android-displaying-dialogs-from-background-threads/
From the stack trace above, it appears that the facebook library spins off the auth operation asynchronously, and you have a Handler - Callback mechanism (onComplete called on a listener) that could easily create this scenario.
When I've seen this reported in my app, its pretty rare and matches the experience in the blog post. Something went wrong for the activity/it was destroyed during the work of the the AsyncTask. I don't know how your modification could result in this every time, but perhaps you are referencing an Activity as the context for the dialog that is always destroyed by the time your code executes?
Also, while I'm not sure if this is the best way to tell if your activity is running, see this answer for one method of doing so:
Check whether activity is active
Unable to add window -- token null is not valid; is your activity running error. How can I solve it?
You're trying to show the popup too early. The view on OnCreate is still not created so try to move the popup() to OnViewCreated()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
popup()
}
or use View.post so it goes into the main thread queue and gets executed after the other pending tasks are finished
override fun onCreate(savedInstanceState: Bundle?) {
...
binding.root.post {
popup()
}
}
Android 'BadTokenException window token android.os.BinderProxy@4250d6d8 is not valid' with foreground service running
Observations
notification = notificationBuilder!!.setOngoing(true)
.setOnlyAlertOnce(true)
.setContentText(textToShowInNotification)
.setContentIntent(contentIntent)
.build()
notificationManager!!.notify(NOTIFICATION_ID, notification)
Clicking on this notification may not start an Activity
because notification
is missing setSmallIcon
or similar setIcon
call. To fix it, set some icon as below:
notification = notificationBuilder!!.setOngoing(true)
.setOnlyAlertOnce(true)
.setContentText(textToShowInNotification)
.setContentIntent(contentIntent)
.setSmallIcon(R.drawable.ic_launcher_background)
.build()
notificationManager!!.notify(NOTIFICATION_ID, notification)
previous activity is not destroyed
That's doubtful because you're using flags Intent.FLAG_ACTIVITY_NEW_TASK|FLAG_ACTIVITY_CLEAR_TASK
when starting an Activity
,and that will finish all previous Activities. Otherwise, please show the relevant code.
When the connection with device is established and data is listened
from service at that time when I kill the app and open it from
foreground service notification, the dialog which has to show up
saying that my device is still connected and data is being received is
not shown
This sounds quite confusing. It sounds like you're showing it from your Activity
, but then it's unlikely to fail, especially, if you show it from onCreate
of your Activity
:
override fun onCreate(savedInstanceState: Bundle?) {
...
showAlertDialog()
}
D/DialogExecption: Unable to add window -- token null is not valid; is
your activity running? D/DialogExecption: Unable to add window token
android.os.BinderProxy@4250d6d8 is not valid; is your activity
running?
The error message is quite clear - you're trying to show a dialog based on an invalid Context
here AlertDialog.Builder(<context>)
. For instance, if you use applicationContext
or a Service
context
there, it will fail with such exception.
You claim to start your dialog with an Activity
context as below:
...
val dialogAlertDialog = AlertDialog.Builder(<Activity Context>)
...
However, it's not clear from your code from where showAlertDialog()
is called, and the context object is not shown either. So, I created a sample project to test the described behaviour.
Suggestion
Preparation
I tried reproducing the issue by building a minimalistic project based on the information that you provided in your question. Please note that I'm not using any BLE functionality for this example, even though Bluetooth is used as a prefix for each component.
I created a foreground service BluetoothDeviceService
responsible for starting an Activity
, when a notification is clicked.
BluetoothDeviceService.kt
class BluetoothDeviceService: Service() {
private val SERVICE_NOTIFICATION_ID = 123
private val SERVICE_NOTIFICATION_CHANNEL_ID = "channel_01"
override fun onCreate() {
super.onCreate()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel(
SERVICE_NOTIFICATION_CHANNEL_ID,
"Bluetooth service",
NotificationManager.IMPORTANCE_DEFAULT)
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.createNotificationChannel(channel)
val pendingIntent = Intent()
pendingIntent.setClass(this,BluetoothDeviceActivity::class.java)
pendingIntent.flags = Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP
val contentIntent = PendingIntent.getActivity(this, 0,
pendingIntent, 0)
val notification = NotificationCompat.Builder(this, SERVICE_NOTIFICATION_CHANNEL_ID)
.setOnlyAlertOnce(true)
.setOngoing(true)
.setContentText("Bluetooth service running...")
.setContentIntent(contentIntent)
.setSmallIcon(R.drawable.ic_launcher_background)
.build()
startForeground(SERVICE_NOTIFICATION_ID, notification)
}
}
override fun onBind(intent: Intent?): IBinder? {
TODO("Not yet implemented")
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
return START_STICKY
}
}
I created a MainActivity
that had to start the foreground service.
MainActivity.kt
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val startServiceIntent = Intent(this, BluetoothDeviceService::class.java)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(startServiceIntent)
} else {
startService(startServiceIntent)
}
finish()
}
}
Please note that the Service
could also be started by BroadcastReceiver
, and that would be more appropriate, but I used the Activity
for simplicity.
Also, I introduced a BluetoothDeviceActivity
that was started by the service with help of PendingIntent
:
BluetoothDeviceActivity.kt
class BluetoothDeviceActivity: AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
showAlertDialog()
}
}
private fun showAlertDialog() {
val dialogAlertDialog = AlertDialog.Builder(this)
.setCancelable(false)
.setMessage("This is a test")
.setTitle("Information")
.create()
dialogAlertDialog.show()
}
Just in case, I also put my manifest.
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.stackoverflowquestion2">
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<application
android:name=".MainApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.StackOverflowQuestion2"
android:fullBackupContent="@xml/backup_descriptor">
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:theme="@style/Theme.StackOverflowQuestion2.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity android:name=".BluetoothDeviceActivity"/>
<service android:name=".BluetoothDeviceService"/>
</application>
</manifest>
Result
This worked as expected without any problems.
Further suggestion
One other idea - you could convert your AlertDialog
to Activity
and use it as a Dialog
. For this, you need to do 2 things:
Create a new
Àctivity
as below:class AlertDialogActivity: AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val dialogAlertDialog = AlertDialog.Builder(this)
.setCancelable(false)
.setMessage("This is a test")
.setTitle("Information")
.setPositiveButton("OK") { dialog, which -> finish() }
.create()
dialogAlertDialog.show()
}
}Add it to your manifest and set its theme as
Dialog
:<activity android:name=".AlertDialogActivity" android:theme="@style/Theme.AppCompat.Dialog"/>
Then, create a method in your
Service
, and use it any time it's needed:private fun showAlertDialog() {
val intent = Intent(applicationContext, AlertDialogActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
applicationContext.startActivity(intent)
}
Result
That's what it looks like:
Related Topics
Failed to Resolve Com.Android.Support:Appcompat-V7:22 and Com.Android.Support:Recyclerview-V7:21.1.2
How to Open or Simulate a Click on an Android Preference, Created with Xml, Programmatically
Realmchangelistener Does Not Get Called When Realm Gets Updated in Notificationlistenerservice
Force Update of an Android App When a New Version Is Available
Error:(26, 0) Gradle Dsl Method Not Found: 'Runproguard()'
Error Importing Holoeverywhere
Date Formatting Based on User Locale on Android
Getlastknownlocation Always Return Null After I Re-Install the APK File via Eclipse
How to Make Circle Custom Progress Bar in Android
Removing Unused Strings During Proguard Optimisation
Create and Share a File from Internal Storage
How Do Mpandroidchart Renderers Work and How to Write a Custom Renderer
How to Set Custom Actionbar Color/Style
Passing Argument to Dialogfragment