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

android – 在XE16中调用openOptionsMenu()会导致WindowManager.BadTokenException,第1张

概述我有一个GDE应用程序在XE12中运行良好但现在在转换到GDK之后在XE16中崩溃:19.特别是,在Activity中调用openOptionsMenu()(在这种情况下,打开Live Card上的选项菜单)会导致BadTokenExceptions. Logcat输出: 04-16 03:36:43.197: E/AndroidRuntime(2465): FATAL EXCEPTION: ma 我有一个GDE应用程序在XE12中运行良好但现在在转换到GDK之后在XE16中崩溃:19.特别是,在Activity中调用openoptionsMenu()(在这种情况下,打开live Card上的选项菜单)会导致BadTokenExceptions.

Logcat输出:

04-16 03:36:43.197: E/AndroIDRuntime(2465): FATAL EXCEPTION: main04-16 03:36:43.197: E/AndroIDRuntime(2465): Process: com.voIDstar.glass.sample.pinDrop,PID: 246504-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.access0(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

服务中将活动绑定到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,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 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上的内部异常).

解决方法 As petey said,但除了onResume()之外,还需要覆盖onAttachedToWindow().我的代码现在看起来像:
private boolean isAttached = false;@OverrIDepublic voID onAttachedToWindow() {  super.onAttachedToWindow();  this.isAttached = true;  openoptionsMenu();}@OverrIDepublic voID onResume() {  super.onResume();  if (this.isAttached)    openoptionsMenu();}
总结

以上是内存溢出为你收集整理的android – 在XE16中调用openOptionsMenu()会导致WindowManager.BadTokenException全部内容,希望文章能够帮你解决android – 在XE16中调用openOptionsMenu()会导致WindowManager.BadTokenException所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1140850.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-31
下一篇 2022-05-31

发表评论

登录后才能评论

评论列表(0条)

保存