I have an view called SpotOnView
, and is extending on Game_shooting_AB
. Coding as follows.
In the SpotOnView there is a countdown timer. When the time is up, the game is over, and a dialog box will popup to ask whether the user would like to quit or play again.
public class SpotOnView extends View
{
......
// constructs a new SpotOnView
public SpotOnView(Context context, RelativeLayout parentLayout)
{
super(context);
resources = context.getResources();
layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
....
}
public void start_timer()
{
if (!timerHasStarted)
{
countDownTimer.start();
timerHasStarted = true;
}
else
{
countDownTimer.cancel();
timerHasStarted = false;
}
}
public class MyCountDownTimer extends CountDownTimer
{
public MyCountDownTimer(long startTime, long interval)
{
super(startTime, interval);
}
@Override
public void onFinish()
{
text.setText("Time's up!");
((Game_shooting_AB)getContext()).replay_dialog(); //LINE 181
}
@Override
public void onTick(long millisUntilFinished)
{
....
}
}
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.game_shooting);
// create a new SpotOnView and add it to the RelativeLayout
RelativeLayout layout = (RelativeLayout) findViewById(R.id.relativeLayout);
view = new SpotOnView(this, layout); //EXTENDING HERE
layout.addView(view, 0); // add view to the layout
....
}
public void replay_dialog()
{
final Dialog dialog1 = new Dialog(Game_shooting_AB.this, android.R.style.Theme_Translucent_NoTitleBar);
WindowManager.LayoutParams lp = dialog1.getWindow().getAttributes();
lp.dimAmount = 0.7f;
dialog1.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
Window window = dialog1.getWindow();
window.setGravity(Gravity.CENTER);
dialog1.setContentView(R.layout.alert_dialog_replay_shooting);
dialog1.setCancelable(false);
dialog1.show(); //LINE 431
....
The necessary line numbers have added as comment in the above codes.
11-22 00:16:34.365: W/dalvikvm(1105): threadid=1: thread exiting with uncaught exception (group=0x41f342a0)
11-22 00:16:34.370: E/AndroidRuntime(1105): FATAL EXCEPTION: main
11-22 00:16:34.370: E/AndroidRuntime(1105): android.view.WindowManager$BadTokenException: Unable to add window -- token android.os.BinderProxy@43304558 is not valid; is your activity running?
11-22 00:16:34.370: E/AndroidRuntime(1105): at android.view.ViewRootImpl.setView(ViewRootImpl.java:708)
11-22 00:16:34.370: E/AndroidRuntime(1105): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:346)
11-22 00:16:34.370: E/AndroidRuntime(1105): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:224)
11-22 00:16:34.370: E/AndroidRuntime(1105): at android.view.WindowManagerImpl$CompatModeWrapper.addView(WindowManagerImpl.java:149)
11-22 00:16:34.370: E/AndroidRuntime(1105): at android.view.Window$LocalWindowManager.addView(Window.java:554)
11-22 00:16:34.370: E/AndroidRuntime(1105): at android.app.Dialog.show(Dialog.java:277)
11-22 00:16:34.370: E/AndroidRuntime(1105): at com.app.abc.Game_shooting_AB.replay_dialog(Game_shooting_AB.java:431)
11-22 00:16:34.370: E/AndroidRuntime(1105): at com.app.abc.SpotOnView$MyCountDownTimer.onFinish(SpotOnView.java:181)
11-22 00:16:34.370: E/AndroidRuntime(1105): at android.os.CountDownTimer$1.handleMessage(CountDownTimer.java:118)
11-22 00:16:34.370: E/AndroidRuntime(1105): at android.os.Handler.dispatchMessage(Handler.java:99)
11-22 00:16:34.370: E/AndroidRuntime(1105): at android.os.Looper.loop(Looper.java:137)
11-22 00:16:34.370: E/AndroidRuntime(1105): at android.app.ActivityThread.main(ActivityThread.java:4898)
11-22 00:16:34.370: E/AndroidRuntime(1105): at java.lang.reflect.Method.invokeNative(Native Method)
11-22 00:16:34.370: E/AndroidRuntime(1105): at java.lang.reflect.Method.invoke(Method.java:511)
11-22 00:16:34.370: E/AndroidRuntime(1105): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1008)
11-22 00:16:34.370: E/AndroidRuntime(1105): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:775)
11-22 00:16:34.370: E/AndroidRuntime(1105): at dalvik.system.NativeStart.main(Native Method)
The logcat shows is your activity running?
I know that the dialog need to have a base to showup. But how could the code be modified?
Would it be possible to code and show the dialog in the SpotOnView
instead of writing in the Game_shooting_AB
code?
I have tried to modify the code by moving the class MyCountDownTimer and method replay_dialog back to Game_shooting_AB, but the same error still comes out. I would like to ask whether the OnFinish of the MyCountDownTimer will bring the Activity to finish such that the dialog does not able to find base to be shown on?
Thanks so much!!
The problem started from "((Game_shooting_AB)getContext()).replay_dialog();" this line of code.
As you will find from documentation of android when you call getContext() from inside of a view you get "The view's Context.". Now what you are doing is casting that context to Game_shooting_AB which is not good since that might or might not be the Activity's context. Checkout Romain Guy's answer about this. Thus android is telling you "is your activity running?".
Now to solve your current problem you can pass your activity instance to this view via any public method and have it store in a local variable.
Adjust your code like this:
public class SpotOnView extends View
{
Game_shooting_AB mGame_shooting_AB;
public void setGame_shooting_AB(Game_shooting_AB mGame_shooting_AB){
this.mGame_shooting_AB = mGame_shooting_AB;
}
......
// constructs a new SpotOnView
public SpotOnView(Context context, RelativeLayout parentLayout)
{
super(context);
resources = context.getResources();
layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
....
}
public void start_timer()
{
if (!timerHasStarted)
{
countDownTimer.start();
timerHasStarted = true;
}
else
{
countDownTimer.cancel();
timerHasStarted = false;
}
}
public class MyCountDownTimer extends CountDownTimer
{
public MyCountDownTimer(long startTime, long interval)
{
super(startTime, interval);
}
@Override
public void onFinish()
{
text.setText("Time's up!");
mGame_shooting_AB.replay_dialog(); //LINE 181
}
@Override
public void onTick(long millisUntilFinished)
{
....
}
}
After you get the instance of SpotOnView set the activity:
view = new SpotOnView(this, layout); //EXTENDING HERE
layout.addView(view, 0); // add view to the layout
view.setGame_shooting_AB(Game_shooting_AB.this);
Hope this helps.