android इस स्टैक ट्रेस के साथ मेरी दुर्घटना का कारण पता नहीं कर सकता




सड़क दुर्घटनाओं की रोकथाम (5)

मेरा ऐप क्या करता है, वह WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAYwindowManager.addView() और WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY windowManager.addView() साथ जुड़ा हुआ सिस्टम ओवरले दृश्य प्रदर्शित करना है। WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY फ़्लैग यह सेवा के साथ किया जाता है, जो कि दृश्यता और कुछ अन्य चीजों को देखता है।

हालांकि, मैं क्रैश रिपोर्ट प्राप्त कर रहा हूं और उन्हें पुन: उत्पन्न नहीं कर सकता। इसके अलावा क्रैश स्टैक ट्रेस का मेरे ऐप के पैकेज के साथ कुछ नहीं करना है, इसलिए मैं वास्तव में इस समस्या की जड़ नहीं पा सकता। निम्नलिखित दो स्टैकेट्स हैं जो विभिन्न स्रोतों से आते हैं, लेकिन उनमें से संबंधित होना जरूरी है:

java.lang.NullPointerException: Attempt to invoke virtual method 'void android.view.View.measure(int, int)' on a null object reference
at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2388)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2101)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1297)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7011)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:777)
at android.view.Choreographer.doCallbacks(Choreographer.java:590)
at android.view.Choreographer.doFrame(Choreographer.java:560)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:763)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:6938)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1404)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1199)

java.lang.NullPointerException: Attempt to invoke virtual method 'int android.view.View.getMeasuredWidth()' on a null object reference
at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2484)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2181)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1293)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6599)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:800)
at android.view.Choreographer.doCallbacks(Choreographer.java:603)
at android.view.Choreographer.doFrame(Choreographer.java:572)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:786)
at android.os.Handler.handleCallback(Handler.java:815)
at android.os.Handler.dispatchMessage(Handler.java:104)
at android.os.Looper.loop(Looper.java:194)
at android.app.ActivityThread.main(ActivityThread.java:5616)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:959)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:754)

ऐसा लगता है कि ओएस (व्यूआरूटइमप्ल) इस समस्या का कारण बना रहा है क्योंकि यह मेरे दृश्य के लिए एक रिक्त संदर्भ का मालिक है इसलिए मुझे इसके लिए एक वैकल्पिक हल नहीं मिल सकता है।

ऐसा लगता है कि 4.4 एंड्रॉइड के सभी संस्करणों में ऐसा होता है और मेरा ऐप प्रोगूर्ड होता है। ये स्टैक निशान Google Play Store क्रैश रिपोर्ट से प्राप्त किए जाते हैं

यहां बताया गया है कि कैसे मैं एक ओवरले के रूप में सिस्टम विंडो को दृश्य देता है:

private void attachToSystemWindows(boolean overlayNavigationBar) {
    final WindowManager windowManager = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);

    final DisplayMetrics metrics = new DisplayMetrics();
    windowManager.getDefaultDisplay().getMetrics(metrics);

    final boolean isNavBarInBottom = isNavBarInBottom();

    final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
            calculateWindowWidth(overlayNavigationBar, isNavBarInBottom, metrics, mNavigationBarHeight),
            calculateWindowHeight(overlayNavigationBar, isNavBarInBottom, metrics, mNavigationBarHeight),
            0,
            0,
            WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
            0x50728,
            -3
    );
    params.gravity = Gravity.TOP;

    windowManager.addView(this, params);
}

private  boolean isNavBarInBottom() {
    final boolean isLargeDevice = getResources().getConfiguration().smallestScreenWidthDp >= 600;
    final int orientation = getResources().getConfiguration().orientation;

    if (BuildConfig.DEBUG)
        Log.d("MeshView", "Is NavBar in bottom: " + (isLargeDevice || orientation == Configuration.ORIENTATION_PORTRAIT));


    return isLargeDevice || orientation == Configuration.ORIENTATION_PORTRAIT;
}

और मेरी मेज़र विधि:

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    if (BuildConfig.DEBUG) Log.d("MeshView", "OnMeasure");
    setMeasuredDimension(
            Math.max(getSuggestedMinimumWidth(), resolveSize(SIZE_MIN_WIDTH, widthMeasureSpec)),
            Math.max(getSuggestedMinimumHeight(), resolveSize(SIZE_MIN_HEIGHT, heightMeasureSpec))
    );
}

https://code.i-harness.com


प्रोगुअर स्टैक ट्रेस इश्यू का कारण बना सकता है, हालांकि आपके कोड का संकेत होना चाहिए था, भले ही उस आवश्यकता को पढ़ना आवश्यक हो, इसलिए मुझे स्टंप दिया गया, ग्रेडल के माध्यम से प्रोगार्ड को बंद कर दिया, फिर से चलाएं और देखें।


मुझे लगता है कि आप params बनाने के दौरान सही फ्लैग नहीं जा रहे हैं।

final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
        calculateWindowWidth(overlayNavigationBar, isNavBarInBottom, metrics, mNavigationBarHeight),
        calculateWindowHeight(overlayNavigationBar, isNavBarInBottom, metrics, mNavigationBarHeight),
        0,
        0,
        WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
        0x50728, // problem might be here.
        -3
);

यह इन मूल्यों में से एक होना चाहिए

तो इसे इस तरह से कुछ का उपयोग करें (सीधे हेक्स मूल्यों से बचें):

final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
        calculateWindowWidth(overlayNavigationBar, isNavBarInBottom, metrics, mNavigationBarHeight),
        calculateWindowHeight(overlayNavigationBar, isNavBarInBottom, metrics, mNavigationBarHeight),
        0,
        0,
        WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
        WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON, //any flag
        PixelFormat.TRANSLUCENT
);

मैंने पिक्सल फ़ॉर्मेट भी संदर्भित किया है

इस तरह बदलने की कोशिश करें और देखें कि क्या काम करता है।


कॉल की श्रृंखला के बाद ViewRoot.dispatchDetachedFromWindow () जो दृश्य रूप से शून्य के दृश्य को सेट करने के बाद ( windowManager.removeView(this) ) द्वारा दृश्य को निकालते समय कम हो जाता है, यही वजह है कि ट्रैवर्सल में आपके पास एनपीई है।

विवरण में:

windowManager.removeView(this);

आप अनिवार्य रूप से दृश्य के ViewRoot पर मर जाते हैं, जो फिर MSG_DIE को अपने हैंडलर पर भेजता है, इसलिए इसे बाद में जब मारता है तब सुरक्षित होता है और mDyingViews में देखने के लिए mDyingViews सूची को जोड़ता है। यह सब ठीक है,

हालांकि कॉल करके:

windowManager.addView(this, layoutParams);

आप ViewRoot की मृत्यु को मजबूर करते हैं और डोडी कॉल doDie() और लगातार ViewRoot.dispatchDetachedFromWindow() जो ट्रवर्सल के दौरान व्यू को सेट करता है और आपके पास एनपीई है।

अधिक जानकारी के लिए WindowManagerGlobal और ViewRootImpl की जांच करें


मुझे अपने ऐप में एक ही समस्या थी, मैंने इस समस्या का उपयोग करके हल किया

public static final int TYPE_SYSTEM_ALERT; 

TYPE_SYSTEM_OVERLAY के बजाय मुझे लगता है कि दृश्य पहले से ही मायाजर () को बुलाया जाता है पर पहले ही नष्ट हो गया है। इस तरह की ओवरले किसी तरह विशेष रूप से नामित प्री किट केट डिवाइस पर एक समस्या पैदा करती है

नोट: यदि आप चाहते हैं कि आपकी ओवरले विंडो स्टेटस बार के पीछे प्रदर्शित होती है और अभी भी अन्य सभी एप्लिकेशन उपयोग करते हैं;

public static final int TYPE_PHONE;

आशा है कि ये आपकी मदद करेगा।


गजब का। अंत में मुझे मेरी समस्या का मूल पाया गया, लेकिन इसका कारण नहीं ... मैं अपने विचार के साथ कुछ कर रहा था: मैं अपनी ओरिएंटेशन के आधार पर अपने लेआउट onConfigurationChanged() को बदलना चाहता था, इसलिए मैं onConfigurationChanged() ओवरराइड किया।

तो मैंने लेआउट पैरामीटर अपडेट करने के लिए एक गंदा तरीका इस्तेमाल किया: अलग करें और फिर इसे WindowManager फिर से WindowManager , जैसे कि:

@Override
protected void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);

    final ViewGroup.LayoutParams layoutParams = getLayoutParams();
    if (!(layoutParams instanceof  WindowManager.LayoutParams)) return; //Fix for some ClassCastException in Samsung devices

    final WindowManager windowManager = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);

    final DisplayMetrics metrics = new DisplayMetrics();
    windowManager.getDefaultDisplay().getMetrics(metrics);

    final boolean isNavBarInBottom = isNavBarInBottom();

    layoutParams.width = calculateWindowWidth(mOverlayNavigationBar, isNavBarInBottom, metrics, mNavigationBarHeight);
    layoutParams.height = calculateWindowHeight(mOverlayNavigationBar, isNavBarInBottom, metrics, mNavigationBarHeight);
    windowManager.removeView(this);
    windowManager.addView(this, layoutParams);
}

मुझे लगता है कि कुछ बुरा ViewRootImpl वर्ग में होता है, जिसके कारण यह ठीक से ViewRootImpl करने में सक्षम नहीं होता, जिसके कारण त्रुटि उत्पन्न होती है।

इसे ठीक करने के लिए, सिर्फ उचित तरीके से जाना चाहिए: WindowManager.updateViewLayout(); प्रयोग करें WindowManager.updateViewLayout(); तरीका:

@Override
protected void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    if (BuildConfig.DEBUG) Log.d("MeshView", "OnConfigurationChanged");

    final ViewGroup.LayoutParams layoutParams = getLayoutParams();
    if (!(layoutParams instanceof  WindowManager.LayoutParams)) return; //Fix for some ClassCastException in Samsung devices

    final WindowManager windowManager = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);

    final DisplayMetrics metrics = new DisplayMetrics();
    windowManager.getDefaultDisplay().getMetrics(metrics);

    final boolean isNavBarInBottom = isNavBarInBottom();

    layoutParams.width = calculateWindowWidth(mOverlayNavigationBar, isNavBarInBottom, metrics, mNavigationBarHeight);
    layoutParams.height = calculateWindowHeight(mOverlayNavigationBar, isNavBarInBottom, metrics, mNavigationBarHeight);
    //windowManager.removeView(this);    DON'T DO THIS
    //windowManager.addView(this, layoutParams);    DON'T DO THIS

    windowManager.updateViewLayout(this, layoutParams); //DO THIS INSTEAD
}

यह मेरी समस्या को ठीक करने के लिए लगता है मुझे इस पोस्ट के लेखक के लिए धन्यवाद चाहिए, जिसने मुझे यह तय करने की इजाजत दी): एंड्रॉइड: लेआउट का बदलेंपैरा देखें WindowManager द्वारा जोड़ा गया





stack-trace