gpt4 book ai didi

运行前台服务的 Android 'BadTokenException window token android.os.BinderProxy@4250d6d8 is not valid'

转载 作者:行者123 更新时间:2023-12-03 20:42:17 28 4
gpt4 key购买 nike

尝试使用 kotlin 构建一个 android 应用程序,我在其中连接、发送和读取来自 BLE(蓝牙低功耗)设备的数据。我设计了一个 Activity ,它将向我显示连接统计信息和从 BLE 设备接收的数据。我有一个前台服务正在运行,以保持与 BLE 设备的连接处于 Activity 状态并收听统计信息。
我已使用待处理的 Intent 从我的前台服务通知中打开此 Activity 。
以下代码显示了创建通知的方法

private fun getServiceNotification(textToShowInNotification: String)
{
val pendingIntent = Intent(<Static context from application class>,ActivityName::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(<static_context_from_application_class>, 0, pendingIntent, 0)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
val notificationChannel = NotificationChannel("DATA_CHANNEL", <Static context from application class>.resources.getString(R.string.app_name),NotificationManager.IMPORTANCE_DEFAULT)
notificationManager!!.createNotificationChannel(notificationChannel)
}

notification = notificationBuilder!!.setOngoing(true)
.setOnlyAlertOnce(true)
.setContentText(textToShowInNotification)
.setContentIntent(contentIntent)
.build()
notificationManager!!.notify(NOTIFICATION_ID, notification)
}
因为我有一个用例来打开显示 BLE 连接和数据接收的 Activity 。创建了 Activity 的多个实例,并且前一次没有被破坏,因此我无法获取正在运行的 Activity 的上下文,因此我面临在 Activity 中显示警报对话框的问题。
实际用例 - 当我杀死应用程序并从前台服务通知打开它时,当建立与设备的连接并从服务中监听数据时,必须显示的对话框说我的设备仍然连接并且数据正在未显示收到的,当显示对话框时出现异常
尝试显示警报对话框时发生以下错误/异常
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?
我使用下面的代码来显示对话框
private fun showAlertDialog()
{
val dialogAlertDialog = AlertDialog.Builder(<Activity Context>)
val inflater: LayoutInflater = layoutInflater
val dialogAlertView: View = inflater.inflate(R.layout.activity_xml_file,null)
dialogAlertDialog.setView(dialogAlertView)
dialogAlertDialog.setCancelable(false)

val builderAlertDialog : AlertDialog = dialogAlertDialog.create()
try
{
builderAlertDialog.show()
}
catch(exception: Exception)
{
Log.d("DialogExecption",""+exception.message)
}
}
我也试过方法
if (!this.isFinishing)
{
builderAlertDialogCycleCancelled.show()
}
但这也无济于事。上面的代码将抑制执行,但我不想这样做,而是我想不惜一切代价显示对话框。
为了提供一个 pov,我在我的 list 文件中尝试了以下内容,以保持 Activity 的单个实例可能,但这并不奏效。
<activity android:name=".ActivityName"
android:alwaysRetainTaskState="true"
android:launchMode="singleTop"
android:screenOrientation="portrait"
android:theme="@style/AppThemeGeneral">

</activity>
我必须以最好的方式使用警报对话框并且跳过它不是一个选择。
任何帮助都会很棒。
重要提示 - 我在我的 Activity 中使用具有范围 Dispatchers.IO 的协程从 BLE 设备获取数据。

最佳答案

观察

    notification = notificationBuilder!!.setOngoing(true)
.setOnlyAlertOnce(true)
.setContentText(textToShowInNotification)
.setContentIntent(contentIntent)
.build()
notificationManager!!.notify(NOTIFICATION_ID, notification)

单击此通知可能不会启动 Activity因为 notification缺少 setSmallIcon或类似的 setIcon称呼。要修复它,请设置一些图标,如下所示:
     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


这是值得怀疑的,因为您正在使用标志 Intent.FLAG_ACTIVITY_NEW_TASK|FLAG_ACTIVITY_CLEAR_TASK当开始 Activity ,这将完成所有以前的 Activity 。否则,请出示相关代码。

When the connection with device is established and data is listenedfrom service at that time when I kill the app and open it fromforeground service notification, the dialog which has to show upsaying that my device is still connected and data is being received isnot shown


这听起来很困惑。听起来您正在从您的 Activity 中展示它, 但它不太可能失败,特别是如果你从 onCreate 显示它您的 Activity :
override fun onCreate(savedInstanceState: Bundle?) {
...
showAlertDialog()
}

D/DialogExecption: Unable to add window -- token null is not valid; isyour activity running? D/DialogExecption: Unable to add window tokenandroid.os.BinderProxy@4250d6d8 is not valid; is your activityrunning?


错误消息非常清楚 - 您正试图显示一个基于无效 Context 的对话框这里 AlertDialog.Builder(<context>) .例如,如果您使用 applicationContextService context在那里,它会因为这样的异常而失败。
您声称以 Activity 开始对话上下文如下:
...
val dialogAlertDialog = AlertDialog.Builder(<Activity Context>)
...
但是,从您的代码中不清楚 showAlertDialog()被调用,并且上下文对象也没有显示。因此,我创建了一个示例项目来测试所描述的行为。
建议
准备
我尝试通过根据您在问题中提供的信息构建一个简约项目来重现该问题。请注意,我在此示例中没有使用任何 BLE 功能,即使 蓝牙 用作每个组件的前缀。
我创建了一个前台服务 BluetoothDeviceService负责启动 Activity ,当点击通知时。
蓝牙设备服务.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
}
}
我创建了一个 MainActivity那必须启动前台服务。
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()
}
}
请注意 Service也可以由 BroadcastReceiver 启动,这样会更合适,但我使用了 Activity为简单起见。
另外,我介绍了一个 BluetoothDeviceActivity由服务在 PendingIntent 的帮助下启动:
蓝牙设备 Activity .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()
}
以防万一,我也把我的 list 。
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>
结果
这按预期工作,没有任何问题。
进一步的建议
另一种想法 - 你可以转换你的 AlertDialogActivity并将其用作 Dialog .为此,您需要做两件事:
  • 新建Àctivity如下:
    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()
    }
    }
  • 将其添加到您的 list 并将其主题设置为 Dialog :
    <activity android:name=".AlertDialogActivity" android:theme="@style/Theme.AppCompat.Dialog"/>
  • 然后,在您的 Service 中创建一个方法,并在需要时随时使用它:
    private fun showAlertDialog() {
    val intent = Intent(applicationContext, AlertDialogActivity::class.java)
    intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
    applicationContext.startActivity(intent)
    }

  • 结果
    这就是它的样子:
    enter image description here

    关于运行前台服务的 Android 'BadTokenException window token android.os.BinderProxy@4250d6d8 is not valid',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66689566/

    28 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com