TourGuide
TourGuide copied to clipboard
Crash on API 15
My app is crashing for devices on API 15 (4.0.3) when mTutorialHandler.next() is called in my TourGuide sequence. I would appreciate any insight as to why this might be happening. This code is now in production, so I would really like to figure it out!
Logcat output:
11-07 23:48:42.171 6863-6863/com.MyDomain.MyApp W/dalvikvm﹕ threadid=1: thread exiting with uncaught exception (group=0xb3131180)
11-07 23:48:42.171 6863-6863/com.MyDomain.MyApp W/System.err﹕ java.lang.NullPointerException
11-07 23:48:42.171 6863-6863/com.MyDomain.MyApp W/System.err﹕ at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2488)
11-07 23:48:42.171 6863-6863/com.MyDomain.MyApp W/System.err﹕ at android.view.View.draw(View.java:10981)
11-07 23:48:42.171 6863-6863/com.MyDomain.MyApp W/System.err﹕ at android.widget.FrameLayout.draw(FrameLayout.java:450)
11-07 23:48:42.171 6863-6863/com.MyDomain.MyApp W/System.err﹕ at android.view.ViewGroup.drawChild(ViewGroup.java:2887)
11-07 23:48:42.171 6863-6863/com.MyDomain.MyApp W/System.err﹕ at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2489)
11-07 23:48:42.171 6863-6863/com.MyDomain.MyApp W/System.err﹕ at android.view.View.draw(View.java:10981)
11-07 23:48:42.171 6863-6863/com.MyDomain.MyApp W/System.err﹕ at android.view.ViewGroup.drawChild(ViewGroup.java:2887)
11-07 23:48:42.171 6863-6863/com.MyDomain.MyApp W/System.err﹕ at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2489)
11-07 23:48:42.171 6863-6863/com.MyDomain.MyApp W/System.err﹕ at android.view.ViewGroup.drawChild(ViewGroup.java:2885)
11-07 23:48:42.171 6863-6863/com.MyDomain.MyApp W/System.err﹕ at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2489)
11-07 23:48:42.171 6863-6863/com.MyDomain.MyApp W/System.err﹕ at android.view.View.draw(View.java:10981)
11-07 23:48:42.171 6863-6863/com.MyDomain.MyApp W/System.err﹕ at android.view.ViewGroup.drawChild(ViewGroup.java:2887)
11-07 23:48:42.171 6863-6863/com.MyDomain.MyApp W/System.err﹕ at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2489)
11-07 23:48:42.171 6863-6863/com.MyDomain.MyApp W/System.err﹕ at android.view.View.draw(View.java:10981)
11-07 23:48:42.171 6863-6863/com.MyDomain.MyApp W/System.err﹕ at android.widget.FrameLayout.draw(FrameLayout.java:450)
11-07 23:48:42.171 6863-6863/com.MyDomain.MyApp W/System.err﹕ at com.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:2126)
11-07 23:48:42.171 6863-6863/com.MyDomain.MyApp W/System.err﹕ at android.view.ViewRootImpl.draw(ViewRootImpl.java:2026)
11-07 23:48:42.171 6863-6863/com.MyDomain.MyApp W/System.err﹕ at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1634)
11-07 23:48:42.171 6863-6863/com.MyDomain.MyApp W/System.err﹕ at android.view.ViewRootImpl.handleMessage(ViewRootImpl.java:2442)
11-07 23:48:42.171 6863-6863/com.MyDomain.MyApp W/System.err﹕ at android.os.Handler.dispatchMessage(Handler.java:99)
11-07 23:48:42.171 6863-6863/com.MyDomain.MyApp W/System.err﹕ at android.os.Looper.loop(Looper.java:137)
11-07 23:48:42.171 6863-6863/com.MyDomain.MyApp W/System.err﹕ at android.app.ActivityThread.main(ActivityThread.java:4424)
11-07 23:48:42.171 6863-6863/com.MyDomain.MyApp W/System.err﹕ at java.lang.reflect.Method.invokeNative(Native Method)
11-07 23:48:42.171 6863-6863/com.MyDomain.MyApp W/System.err﹕ at java.lang.reflect.Method.invoke(Method.java:511)
11-07 23:48:42.171 6863-6863/com.MyDomain.MyApp W/System.err﹕ at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
11-07 23:48:42.171 6863-6863/com.MyDomain.MyApp W/System.err﹕ at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
11-07 23:48:42.171 6863-6863/com.MyDomain.MyApp W/System.err﹕ at dalvik.system.NativeStart.main(Native Method)
11-07 23:48:42.171 6863-6863/com.MyDomain.MyApp W/FlurryAgent﹕ Error logged: uncaught
11-07 23:48:42.180 6863-6863/com.MyDomain.MyApp E/AndroidRuntime﹕ FATAL EXCEPTION: main
java.lang.NullPointerException
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2488)
at android.view.View.draw(View.java:10981)
at android.widget.FrameLayout.draw(FrameLayout.java:450)
at android.view.ViewGroup.drawChild(ViewGroup.java:2887)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2489)
at android.view.View.draw(View.java:10981)
at android.view.ViewGroup.drawChild(ViewGroup.java:2887)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2489)
at android.view.ViewGroup.drawChild(ViewGroup.java:2885)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2489)
at android.view.View.draw(View.java:10981)
at android.view.ViewGroup.drawChild(ViewGroup.java:2887)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2489)
at android.view.View.draw(View.java:10981)
at android.widget.FrameLayout.draw(FrameLayout.java:450)
at com.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:2126)
at android.view.ViewRootImpl.draw(ViewRootImpl.java:2026)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1634)
at android.view.ViewRootImpl.handleMessage(ViewRootImpl.java:2442)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4424)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
at dalvik.system.NativeStart.main(Native Method)
My code. As far as I can tell from debugging, the last step I reach is mTourGuide.next();
public TourGuide mTutorialHandler;
private void initiateTourGuide() {
initPointer();
initToolTipAnimations();
initOverlay();
initOverlayToPagerFrag();
buildTourGuideSequenceMainFrag();
blocking_view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mTutorialHandler.getOverlay().performClick();
}
});
}
private Pointer pointer;
private void initPointer() {
pointer = new Pointer().setColor(getResources().getColor(R.color.accent)).setGravity(Gravity.BOTTOM | Gravity.LEFT);
}
private Overlay overlay;
private void initOverlay() {
overlay = new Overlay().setStyle(Overlay.Style.Rectangle)
.disableClick(true)
.setEnterAnimation(toolTipEnterAnimation)
.setExitAnimation(toolTipExitAnimation)
.setBackgroundColor(Color.parseColor("#dd151515"))
.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
try {
mTutorialHandler.next(); //*** Last step called in my code ***
} catch (Exception ex){
ex.printStackTrace();
}
}
})
;
}
private Overlay overlayToPagerFrag;
private void initOverlayToPagerFrag() {
overlayToPagerFrag = new Overlay().setStyle(Overlay.Style.Rectangle)
.disableClick(true)
.setEnterAnimation(toolTipEnterAnimation)
.setExitAnimation(toolTipExitAnimation)
.setBackgroundColor(Color.parseColor("#dd151515"))
.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mTutorialHandler.cleanUp();
blocking_view.setVisibility(View.GONE);
Fragment frag = getParentFragment();
if (frag != null) {
if (frag instanceof MainPagerFragment) {
((MainPagerFragment) frag).initiateTourGuide();
}
}
}
})
;
}
private ToolTip toolTip;
Animation toolTipEnterAnimation;
Animation toolTipExitAnimation;
private void initToolTipAnimations() {
/* setup enter and exit animation */
toolTipEnterAnimation = new AlphaAnimation(0f, 1f);
toolTipEnterAnimation.setDuration(800);
toolTipEnterAnimation.setFillAfter(true);
toolTipExitAnimation = new AlphaAnimation(1f, 0f);
toolTipExitAnimation.setDuration(800);
toolTipExitAnimation.setFillAfter(true);
}
private static final int TOUR_TAP_COURSE_STEP = 15;
private static final int TOUR_EXPLAIN_ASSIGNMENTS_STEP = 16;
private static final int TOUR_INDICATE_SCHEDULE_TAB_STEP = 17;
private ToolTip getToolTip(int tutorialStep) {
int ori = getResources().getConfiguration().orientation;
switch (tutorialStep) {
case TOUR_TAP_COURSE_STEP:
toolTip = new ToolTip()
.setTextColor(Color.WHITE)
.setBackgroundColor(Color.TRANSPARENT)
.setShadow(false);
if (ori != Configuration.ORIENTATION_LANDSCAPE) {
toolTip.setTitle("\n" + getActivity().getString(R.string.tour_tap_course));
toolTip.setGravity(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL);
} else {
toolTip.setTitle(getActivity().getString(R.string.tour_tap_course));
toolTip.setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL);
}
return toolTip;
case TOUR_EXPLAIN_ASSIGNMENTS_STEP:
toolTip = new ToolTip()
.setTextColor(Color.WHITE)
.setBackgroundColor(Color.TRANSPARENT)
.setShadow(false);
if (ori != Configuration.ORIENTATION_LANDSCAPE) {
toolTip.setTitle("\n" + getActivity().getString(R.string.tour_approaching_assignments));
toolTip.setGravity(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL);
} else {
toolTip.setTitle(getActivity().getString(R.string.tour_approaching_assignments));
toolTip.setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL);
}
return toolTip;
case TOUR_INDICATE_SCHEDULE_TAB_STEP:
toolTip = new ToolTip()
.setTextColor(getResources().getColor(R.color.primary_dark))
.setBackgroundColor(Color.TRANSPARENT)
.setShadow(true);
if (ori != Configuration.ORIENTATION_LANDSCAPE) {
toolTip.setTitle("\n\n" + getActivity().getString(R.string.assignments_and_schedule));
toolTip.setGravity(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL);
} else {
toolTip.setTitle(getActivity().getString(R.string.assignments_and_schedule));
toolTip.setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL);
}
return toolTip;
default:
return null;
}
}
private void buildTourGuideSequenceMainFrag() {
TourGuide tourGuide1_tapCourse = TourGuide.init(getActivity())
.setPointer(pointer)
.setToolTip(getToolTip(TOUR_TAP_COURSE_STEP))
.playLater(rootView.findViewById(R.id.course_entire_list_card_view));
TourGuide tourGuide2_explainAssignments = TourGuide.init(getActivity())
.setPointer(pointer)
.setToolTip(getToolTip(TOUR_EXPLAIN_ASSIGNMENTS_STEP))
.setOverlay(overlayToPagerFrag)
.playLater(rootView.findViewById(R.id.assignment_entire_list_card_view));
Sequence sequence = new Sequence.SequenceBuilder()
.add(tourGuide1_tapCourse, tourGuide2_explainAssignments)
.setDefaultOverlay(overlay)
.setDefaultPointer(null)
.setContinueMethod(Sequence.ContinueMethod.OverlayListener)
.build();
blocking_view.setVisibility(View.VISIBLE);
mTutorialHandler = TourGuide.init(getActivity()).playInSequence(sequence);
}
}
Same here, everything works fine on Lollipop but crashes on ICS.
/* setup enter and exit animation */
AlphaAnimation mEnterAnimation = new AlphaAnimation(0f, 1f);
mEnterAnimation.setDuration(600);
mEnterAnimation.setFillAfter(true);
AlphaAnimation mExitAnimation = new AlphaAnimation(1f, 0f);
mExitAnimation.setDuration(600);
mExitAnimation.setFillAfter(true);
// the return handler is used to manipulate the cleanup of all the tutorial elements
TourGuide tourGuide1 = TourGuide.init(this)
.setToolTip(new ToolTip()
.setTitle(getString(R.string.tutorial1_title))
.setDescription(getString(R.string.tutorial1))
.setGravity(Gravity.CENTER)
)
// note that there is not Overlay here, so the default one will be used
.playLater(screenCenter);
TourGuide tourGuide2 = TourGuide.init(this)
.setToolTip(new ToolTip()
.setTitle(getString(R.string.tutorial2_title))
.setDescription(getString(R.string.tutorial2))
.setGravity(Gravity.BOTTOM)
.setBackgroundColor(Color.parseColor("#c0392b"))
)
.playLater(noticeContainer);
TourGuide tourGuide3 = TourGuide.init(this)
.setToolTip(new ToolTip()
.setDescription(getString(R.string.tutorial3))
.setGravity(Gravity.BOTTOM)
)
// note that there is not Overlay here, so the default one will be used
.playLater(noticeContainer);
Sequence sequence = new Sequence.SequenceBuilder()
.add(tourGuide1, tourGuide2, tourGuide3)
.setDefaultOverlay(new Overlay()
.setEnterAnimation(mEnterAnimation)
.setExitAnimation(mExitAnimation).setBackgroundColor(Color.parseColor("#8800796B")).setStyle(Overlay.Style.Rectangle)
)
.setDefaultPointer(null)
.setContinueMethod(Sequence.ContinueMethod.Overlay)
.build();
TourGuide.init(this).playInSequence(sequence);
Still not fixed on ICS (API 15) any updates?
06-04 10:32:03.574 6158-6158/xx.xxxx.xxxx.xxxx E/AndroidRuntime: FATAL EXCEPTION: main
java.lang.NullPointerException
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2488)
at android.view.View.draw(View.java:10986)
at android.widget.FrameLayout.draw(FrameLayout.java:450)
at android.view.View.getDisplayList(View.java:10422)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:2597)
at android.view.View.getDisplayList(View.java:10385)
at android.view.ViewGroup.drawChild(ViewGroup.java:2850)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2489)
at android.view.View.draw(View.java:10986)
at android.widget.FrameLayout.draw(FrameLayout.java:450)
at com.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:2126)
at android.view.View.getDisplayList(View.java:10422)
at android.view.HardwareRenderer$GlRenderer.draw(HardwareRenderer.java:849)
at android.view.ViewRootImpl.draw(ViewRootImpl.java:1910)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1634)
at android.view.ViewRootImpl.handleMessage(ViewRootImpl.java:2442)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4424)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
at dalvik.system.NativeStart.main(Native Method)
I had the same problem, and I found that it's caused by the Overlay exit animation. Don't set any exit animation for Android API 15, and it's fixed!