gpt4 book ai didi

android - 在 XE16 中调用 openOptionsMenu() 导致 WindowManager.BadTokenException

转载 作者:塔克拉玛干 更新时间:2023-11-02 20:43:35 26 4
gpt4 key购买 nike

我有一个 GDK 应用程序在 XE12 中运行良好,但现在在转换到 GDK:19 后在 XE16 中崩溃。特别是,在 Activity 中调用 openOptionsMenu()(在这种情况下,打开 Live Card 上的选项菜单)会导致 BadTokenExceptions。

Logcat 输出:

04-16 03:36:43.197: E/AndroidRuntime(2465): FATAL EXCEPTION: main
04-16 03:36:43.197: E/AndroidRuntime(2465): Process: com.voidstar.glass.sample.pinDrop, PID: 2465
04-16 03:36:43.197: E/AndroidRuntime(2465): java.lang.RuntimeException: Unable to resume activity {com.voidstar.glass.sample.pinDrop/com.voidstar.glass.sample.pinDrop.MenuActivity}: android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running?
04-16 03:36:43.197: E/AndroidRuntime(2465): at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2828)
04-16 03:36:43.197: E/AndroidRuntime(2465): at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2857)
04-16 03:36:43.197: E/AndroidRuntime(2465): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2290)
04-16 03:36:43.197: E/AndroidRuntime(2465): at android.app.ActivityThread.access$800(ActivityThread.java:138)
04-16 03:36:43.197: E/AndroidRuntime(2465): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1236)
04-16 03:36:43.197: E/AndroidRuntime(2465): at android.os.Handler.dispatchMessage(Handler.java:102)
04-16 03:36:43.197: E/AndroidRuntime(2465): at android.os.Looper.loop(Looper.java:149)
04-16 03:36:43.197: E/AndroidRuntime(2465): at android.app.ActivityThread.main(ActivityThread.java:5061)
04-16 03:36:43.197: E/AndroidRuntime(2465): at java.lang.reflect.Method.invokeNative(Native Method)
04-16 03:36:43.197: E/AndroidRuntime(2465): at java.lang.reflect.Method.invoke(Method.java:515)
04-16 03:36:43.197: E/AndroidRuntime(2465): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:794)
04-16 03:36:43.197: E/AndroidRuntime(2465): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:610)
04-16 03:36:43.197: E/AndroidRuntime(2465): at dalvik.system.NativeStart.main(Native Method)
04-16 03:36:43.197: E/AndroidRuntime(2465): Caused by: android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running?
04-16 03:36:43.197: E/AndroidRuntime(2465): at android.view.ViewRootImpl.setView(ViewRootImpl.java:561)
04-16 03:36:43.197: E/AndroidRuntime(2465): at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:259)
04-16 03:36:43.197: E/AndroidRuntime(2465): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:69)
04-16 03:36:43.197: E/AndroidRuntime(2465): at com.android.internal.policy.impl.PhoneWindow.openPanel(PhoneWindow.java:693)
04-16 03:36:43.197: E/AndroidRuntime(2465): at com.android.internal.policy.impl.PhoneWindow.openPanel(PhoneWindow.java:555)
04-16 03:36:43.197: E/AndroidRuntime(2465): at android.app.Activity.openOptionsMenu(Activity.java:2878)
04-16 03:36:43.197: E/AndroidRuntime(2465): at com.voidstar.glass.sample.pinDrop.MenuActivity.onResume(MenuActivity.java:71)
04-16 03:36:43.197: E/AndroidRuntime(2465): at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1194)
04-16 03:36:43.197: E/AndroidRuntime(2465): at android.app.Activity.performResume(Activity.java:5316)
04-16 03:36:43.197: E/AndroidRuntime(2465): at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2818)
04-16 03:36:43.197: E/AndroidRuntime(2465): ... 12 more

服务中将 Activity 绑定(bind)到 Live Card 的方法:

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// This method is called whenever the Glassware is invoked via voice commands or the OK Glass menu.
if (mLiveCard == null) {
Log.d(TAG, "Connecting mLocationManager");

Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_COARSE);

PinDropLocationListener listener = new PinDropLocationListener();
locationListeners.add(listener);
mLocationManager.requestSingleUpdate(criteria, listener, null);

mLiveCard = new LiveCard(getBaseContext(), LIVE_CARD_TAG);
mLiveCard.setViews(new RemoteViews(getPackageName(), R.layout.activity_waiting));
mLiveCard.attach(this); // Prevent this Service from being killed to free up memory

Intent menuIntent = new Intent(this, MenuActivity.class); // Since menus can only be attached to Activities, we create an activity to own and launch the menu.
menuIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
mLiveCard.setAction(PendingIntent.getActivity(this, 0, menuIntent, 0)); // This Intent will be fired whenever the LiveCard is tapped.

Log.d(TAG, "Publishing LiveCard");
mLiveCard.publish(PublishMode.REVEAL); // Add the LiveCard to the Timeline and switch to it
Log.d(TAG, "Done publishing LiveCard");
} else {
mLiveCard.navigate(); // Switch to the app if it's already running
}

return START_STICKY; // No idea what this does. Your guess is as good as mine.
}

还有有问题的 Activity:

/**
* Activity showing the options menu.
*/
public class MenuActivity extends Activity {
// This is technically an Immersion!
// Because Services have no UI, we need to open this Activity, which in turn opens its menu!

PinDropService.MenuBinder mBinder;

private static String TAG = "PinDropMenu";

boolean hasLocation;

/*
* Links this Activity to the Service that spawned it, so the Menu can send and receive information
*/
private ServiceConnection mConnection = new ServiceConnection() {

@Override
public void onServiceConnected(ComponentName name, IBinder service) {
if (service instanceof PinDropService.MenuBinder) {
mBinder = (PinDropService.MenuBinder)service;
hasLocation = mBinder.hasLocation();
Log.d(TAG, hasLocation ? "Received has location" : "Received no location");
//openOptionsMenu();
}
}

@Override
public void onServiceDisconnected(ComponentName name) {}
};

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
bindService(new Intent(this, PinDropService.class), mConnection, 0);
}

@Override
public void onResume() {
super.onResume();
openOptionsMenu();
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.pindropmenu, menu);
return true;
}

@Override
public boolean onPrepareOptionsMenu(Menu menu) {
if (!hasLocation) {
menu.findItem(R.id.directions).setVisible(false);
menu.findItem(R.id.remember).setVisible(false);
}
else {
menu.findItem(R.id.directions).setVisible(true);
menu.findItem(R.id.remember).setVisible(true);
}
return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle item selection.
switch (item.getItemId()) {
case R.id.directions:
mBinder.startNavigation();
return true;
case R.id.remember:
mBinder.addToTimeline(); // TODO: Add Mirror functionality!
return true;
case R.id.stop: // IT IS CRITICALLY IMPORTANT TO ADD THIS OR THE GLASSWARE CAN'T BE KILLED IN USERSPACE!
stopService(new Intent(this, PinDropService.class));
return true;
default:
return super.onOptionsItemSelected(item);
}
}

@Override
public void onOptionsMenuClosed(Menu menu) {
// Nothing else to do, closing the Activity.
finish();
}

@Override
public void onStop() {
super.onStop();
unbindService(mConnection); // Don't leak Services!
}
}

点击 Live Card 会导致立即崩溃,并且会转储上面的 Logcat 输出。奇怪的是,如果注释掉的 openOptionsMenu() 未被注释掉并且现有的 openOptionsMenu() 被注释掉,那么第一次点击实际上会打开菜单。第二次尝试打开菜单将失败,并显示类似的 Logcat 输出(BadTokenException 是主要异常,而不是 RuntimeException 上的内部异常)。

最佳答案

来自 skylight1 中 dario 的回答,

“示例也已更新 - 来自 Compass:”

@Override
public void onAttachedToWindow() {
super.onAttachedToWindow();
mAttachedToWindow = true;
openOptionsMenu();
}

泰达里奥!

关于android - 在 XE16 中调用 openOptionsMenu() 导致 WindowManager.BadTokenException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23103736/

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