IllegalStateException:片段xx未附加到活动

时间:2019-05-24 20:52:35

标签: android

我正在构建一个包含1个主要活动和5个片段的应用程序。片段之一仅在我旋转设备(从纵向到横向)时触发异常。如果我将片段保持为纵向模式,并且在其他4个组件中均不存在问题,则它工作得很好。 该片段完全出于应用内购买的目的而组成。
Logcat抱怨的3行对我来说意义不大,因为它们非常不同,并且实际上并没有关注相同的事物。

主要活动:

public class Monthly_paid extends AppCompatActivity implements BottomNavigationView.OnNavigationItemSelectedListener, NavigationView.OnNavigationItemSelectedListener {

    private static final String TAG = "Monthly_paid";

    private DrawerLayout drawer;
    private BottomNavigationView botnav;

    private AdView mAdView;
    private SharedPreferences mSharedPreferences;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_monthly_paid);
        mAdView = findViewById(R.id.adView);

        botnav = findViewById(R.id.navigation);
        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        drawer = findViewById(R.id.nav_drawer_layout);
        ActionBarDrawerToggle toogle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
        drawer.addDrawerListener(toogle);
        toogle.syncState();

        mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);

        NavigationView drawerNavigation = findViewById(R.id.nav_view);
        drawerNavigation.setNavigationItemSelectedListener(this);
        BottomNavigationView bottomNavigation = findViewById(R.id.navigation);
        bottomNavigation.setOnNavigationItemSelectedListener(this);

        //Sætter titlen i toolbar, til at være nedenstående string
        //Monthly_paid.this.setTitle(getText(R.string.app_name));
        getSupportActionBar().setTitle(getText(R.string.app_name));

        //Gør så Home er highlighted ved launch
        drawerNavigation.setCheckedItem(R.id.navigation_home);

        loadFragment(new MonthlyFragment());

        //2 next lines is to find users FCM token, for firebase notifications
//        String myRefreshedToken = FirebaseInstanceId.getInstance().getToken();
//        Log.d( "myRefreshedToken" , myRefreshedToken);


    }
    //Checker for shared preferences ved launch, og sætter dem som de skal være
    private void checkSharedPreferences(){
        boolean adFree = mSharedPreferences.getBoolean(getString(R.string.remove_ads_key), false);
        Log.d(TAG, "Check SharedPref Start");
        if (adFree == false){
            Log.d(TAG, "Adfree Ikke Købt");

            MobileAds.initialize(this, "@string/ads_test_id");
            AdRequest adRequest = new AdRequest.Builder().build();
            mAdView.loadAd(adRequest);
            mAdView.setVisibility(View.VISIBLE);
        }else{
            Log.d(TAG, "Adfree Købt");
            mAdView.setVisibility(View.INVISIBLE);
        }
    }

    private boolean loadFragment (Fragment fragment) {

        if(fragment != null){

            getFragmentManager()
                    .beginTransaction()
                    .replace(R.id.fragment_container, fragment)
                    .commit();

            return true;
        }
        return false;
    }

    @Override
    public boolean onNavigationItemSelected(@NonNull MenuItem item) {

        Fragment fragment = null;

        switch (item.getItemId()){
            // Bottom Navigation
            case R.id.navigation_monthly:
                fragment = new  MonthlyFragment();
                break;

            case R.id.navigation_hourly:
                fragment = new HourlyFragment();
                break;

            case R.id.navigation_vat:
                fragment = new VATFragment();
                break;

                //Navigation Drawer(Sidebar)
            case R.id.navigation_home:
                fragment = new MonthlyFragment();
                //Gør bottom navigation bar synlig
                getSupportActionBar().setTitle(getText(R.string.app_name));
                botnav.setVisibility(View.VISIBLE);
                break;

           /* case R.id.navigation_about_us:
                fragment = new AboutUsFragment();
                break;*/

            case R.id.navigation_documents:
                fragment = new PopUpPrivacy();
                //Fjerner bottom navigation bar
                botnav.setVisibility(View.GONE);
                break;

            case R.id.navigation_premium:
                fragment = new InAppBilling();
                botnav.setVisibility(View.GONE);
                break;

        }

        drawer.closeDrawer(GravityCompat.START);
        return loadFragment(fragment);
    }


    @Override
    public void onBackPressed(){
        if (drawer.isDrawerOpen(GravityCompat.START)){
            drawer.closeDrawer(GravityCompat.START);
        }
        else{
            super.onBackPressed();
        }
    }

     @Override
    public void onResume(){
         super.onResume();
         checkSharedPreferences();
         //Sætter titlen i toolbar, til at være nedenstående string
         getSupportActionBar().setTitle(getText(R.string.app_name));
         //Monthly_paid.this.setTitle(getText(R.string.app_name));
     }

}

麻烦的片段:

public class InAppBilling extends Fragment implements PurchasesUpdatedListener, View.OnClickListener {

    private static final String TAG = "InAppBilling";

    //In APP Produkter
    static final String ITEM_SKU_ADREMOVAL = "remove_ads_salary1";

    private Button mButton;
    private Button back_Button;
    private String mAdRemovalPrice;
    private SharedPreferences mSharedPreferences;
    private SharedPreferences.Editor mEditor;
    private String purchaseToken;

    private BillingClient mBillingClient;

    private DrawerLayout drawer;
    private BottomNavigationView botnav;

    private FirebaseAnalytics mFirebaseAnalytics;


@Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.inappbilling, container, false);

        mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
        mEditor = mSharedPreferences.edit();

        //Sætter titlen i toolbar, til at være nedenstående string
        ((Monthly_paid)getActivity()).getSupportActionBar().setTitle(getText(R.string.title_premium));

        mButton = v.findViewById(R.id.buy_button);

        v.findViewById(R.id.buy_button).setOnClickListener(this);

        mBillingClient = BillingClient.newBuilder(getActivity()).setListener(this).build();
        mBillingClient.startConnection(new BillingClientStateListener() {
            @Override
            public void onBillingSetupFinished(int responseCode) {
                if (responseCode == BillingClient.BillingResponse.OK){
                    List skuList = new ArrayList<>();
                    skuList.add(ITEM_SKU_ADREMOVAL);
                    SkuDetailsParams.Builder params = SkuDetailsParams.newBuilder();
                    params.setSkusList(skuList).setType(BillingClient.SkuType.INAPP);

                    //Kører 2 nedenstående metoder, når activity åbnes - Tjekker om der er betalt for adFree
                    checkPurchaseHistory();
                    checkPurchases();
                    checkSharedPreferences();
                    mBillingClient.querySkuDetailsAsync(params.build(),
                            new SkuDetailsResponseListener() {
                                @Override
                                public void onSkuDetailsResponse(int responseCode, List<SkuDetails> skuDetailsList) {
                                    //Processing the response if the code = OK, and skuDetailsList isn't = null(empty)
                                    if (responseCode == BillingClient.BillingResponse.OK && skuDetailsList != null){
                                        for (SkuDetails skuDetails : skuDetailsList){
                                            String sku = skuDetails.getSku();
                                            String price = skuDetails.getPrice();
                                            if (ITEM_SKU_ADREMOVAL.equals(sku)){
                                                mAdRemovalPrice = price;
                                                boolean adFree = mSharedPreferences.getBoolean(getString(R.string.remove_ads_key), false);
                                                if (adFree == false) {
                                                    //Sætter teksten af købs knappen, til at være lig med prisen på at købe ad removal, hvis adRemoval ikke er købt
                                                    mButton.setText(mAdRemovalPrice);
                                                }
                                            }
                                        }
                                    }
                                }
                            });
                }
            }

            @Override
            public void onBillingServiceDisconnected() {
                // IMPLEMENT RETRY POLICY - TRY TO RESTART ON NEXT REQUEST BY CALLING startConnection()
            }
        });
        return v;
    }

    @Override
    public void onPurchasesUpdated(int responseCode, @Nullable List<Purchase> purchases) {
        // Hvis bruger køber genstand
        if (responseCode == BillingClient.BillingResponse.OK && purchases != null){
            for (Purchase purchase : purchases){
                handlePurchase(purchase);
                Log.d(TAG, "onPurchaseUpdated() response: " + responseCode);
                String purchasedSku = purchase.getSku();
                Log.i(TAG, "Purchased SKU: " + purchasedSku);
                this.purchaseToken = purchase.getPurchaseToken();
            }
        }// Hvis bruger annullerer købet
        else if (responseCode == BillingClient.BillingResponse.USER_CANCELED){
            Toast.makeText((getActivity()), R.string.purchase_cancelled, Toast.LENGTH_LONG).show();
            Log.d(TAG, "USER CANCELED, Error code: " + responseCode);
        }/// Hvis bruger allerede ejer genstanden
        else if (responseCode == BillingClient.BillingResponse.ITEM_ALREADY_OWNED){
            Log.d(TAG, "ITEM ALREADY OWNED");
            mEditor.putBoolean((getResources().getString(R.string.remove_ads_key)), true);
            mEditor.commit();
            mButton.setText(getResources().getString(R.string.ads_already_purchased));
            mButton.setEnabled(false);
            mButton.setBackground(ContextCompat.getDrawable(getActivity(), R.drawable.button_rounded_gray));

        }
        else{//Any other Error
            Log.d(TAG, "Billing Client ERROR Response code: " + responseCode);
        }

    }

    private void handlePurchase(Purchase purchase){
        if (purchase.getSku().equals(ITEM_SKU_ADREMOVAL)){
            Log.d(TAG, "AD Removal Købt!");

        }
    }

    @Override
    public void onClick(View view) {
        if (view.getId() == R.id.buy_button) {
            BillingFlowParams flowParams = BillingFlowParams.newBuilder()
                    // .setSkuDetails(skuDetails)
                    .setSku(ITEM_SKU_ADREMOVAL)
                    .setType(BillingClient.SkuType.INAPP)
                    .build();
            int responseCode = mBillingClient.launchBillingFlow(getActivity(), flowParams);

        }
    }



    private void checkSharedPreferences(){
        boolean adFree = mSharedPreferences.getBoolean(getString(R.string.remove_ads_key), false);
        Log.d(TAG, "**********");
        Log.d(TAG, "CHECK SHARED PREFERENCE START");
        if (adFree == false){
            Log.d(TAG, "IKKE KØBT ADFREE");
            Log.d(TAG, "**********");
            mButton.setText(R.string.ads_buy_button);
            mButton.setEnabled(true);
            mButton.setBackground(ContextCompat.getDrawable(getActivity(),R.drawable.button_rounded_green));
        }else{
            Log.d(TAG, "ADFREE KØBT");
            Log.d(TAG, "**********");
            mButton.setText(getResources().getString(R.string.ads_already_purchased));
            mButton.setEnabled(false);
            mButton.setBackground(ContextCompat.getDrawable(getActivity(), R.drawable.button_rounded_gray));
        }
    }

    private void checkPurchases(){
        Purchase.PurchasesResult queryResult = mBillingClient.queryPurchases(BillingClient.SkuType.INAPP);
        Log.d(TAG, "**********");
        Log.d(TAG, "CHECK PURCHASES START");
        if(queryResult.getPurchasesList() != null){
            Log.d(TAG, "QUERY LISTE IKKE NULL");
            if (queryResult.getPurchasesList().size() > 0) {
                Log.d(TAG, "Query Liste over 0");
                for (Purchase result : queryResult.getPurchasesList()) {
                    Log.d(TAG, "Bought OrderID: " + result.getOrderId());
                    Log.d(TAG, "Bought JSON: " + result.getOriginalJson());
                    Log.d(TAG, "Bought Token: " + result.getPurchaseToken());
                    if (result.getSku().equals(ITEM_SKU_ADREMOVAL)) {
                        Log.d(TAG, "ADREMOVAL FUNDET I CHECK PURCHASES");
                        Log.d(TAG, "**********");
                        mEditor.putBoolean((getResources().getString(R.string.remove_ads_key)), true);
                        mEditor.commit();
                    } else if (!result.getSku().equals(ITEM_SKU_ADREMOVAL)) {
                        Log.d(TAG, "ADREMOVAL IKKE FUNDET I CHECK PURCHASES");
                        Log.d(TAG, "**********");
                        mEditor.putBoolean((getResources().getString(R.string.remove_ads_key)), false);
                        mEditor.commit();
                    }
                }
            }else {
                mEditor.putBoolean((getResources().getString(R.string.remove_ads_key)), false);
                mEditor.commit();
            }
        }else{
            mEditor.putBoolean((getResources().getString(R.string.remove_ads_key)), false);
            mEditor.commit();
            Log.d(TAG, "INTET FUNDET I QUERY LISTE");
            Log.d(TAG, "**********");
        }
    }

    private void checkPurchaseHistory(){
        mBillingClient.queryPurchaseHistoryAsync(BillingClient.SkuType.INAPP, new PurchaseHistoryResponseListener() {
            @Override
            public void onPurchaseHistoryResponse(int responseCode, List<Purchase> purchasesList) {
                Log.d(TAG, "**********");
                Log.d(TAG, "PURCHASE HISTORY START");
                if (responseCode == BillingClient.BillingResponse.OK){
                    if (purchasesList != null){
                        Log.d(TAG, "PURCHASE HISTORY IKKE = NULL");
                        if (purchasesList.size() > 0){
                            for (Purchase result : purchasesList) {
                                Log.d(TAG, "Bought JSON: " + result.getOriginalJson());
                                Log.d(TAG, "Bought Token: " + result.getPurchaseToken());
                                if (result.getSku().equals(ITEM_SKU_ADREMOVAL)) {
                                    Log.d(TAG, "ITEM REMOVAL FUNDET I PURCHASE HISTORY");
                                    Log.d(TAG, "**********");
                                }else {
                                    Log.d(TAG, "ITEM REMOVAL IKKE FUNDET I PURCHASE HISTORY");
                                    Log.d(TAG, "**********");
                                }
                            }
                        }
                    }
                }
            }
        });
    }

    @Override
    public void onResume() {
        super.onResume();
        checkPurchases();
        checkSharedPreferences();
        ((Monthly_paid)getActivity()).getSupportActionBar().setTitle(getText(R.string.title_premium));
    }

    // Gør det muligt at tracke brug af fragment via Firebase Analytics
    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            mFirebaseAnalytics = FirebaseAnalytics.getInstance(getContext());
        }

    }

}

Logcat消息:

java.lang.IllegalStateException: Fragment InAppBilling{bea3072} not attached to Activity
        at android.app.Fragment.getResources(Fragment.java:768)
        at studios.kundby.skatmomsberegner.InAppBilling.checkPurchases(InAppBilling.java:233)
        at studios.kundby.skatmomsberegner.InAppBilling.access$100(InAppBilling.java:53)
        at studios.kundby.skatmomsberegner.InAppBilling$1.onBillingSetupFinished(InAppBilling.java:102)
        at com.android.billingclient.api.BillingClientImpl$BillingServiceConnection$1.run(BillingClientImpl.java:1155)
        at android.os.Handler.handleCallback(Handler.java:873)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:7045)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:964)

1 个答案:

答案 0 :(得分:0)

有两个问题:

  1. 您正在无条件调用loadFragment(new MonthlyFragment());的{​​{1}}中的Monthly_paid。片段会自动恢复其状态,因此只能onCreate()执行此操作,以避免覆盖要还原的片段。

  2. 您永远不会调用mBillingClient.endConnection(),因此当您的Fragment被销毁时,任何异步回调(例如您的if (savedInstanceState == null))都不会被取消。由于您在onBillingSetupFinished()中调用startConnection(),因此放置onCreateView()的逻辑位置在endConnection()中。