I'm building an app which consist of 1 main activity, and so far 5 fragments. One of the fragments, triggers an exception only when i rotate the device, from portrait to landscape. It works just fine, if I keep the fragment in portrait mode, and no issues exists in the other 4 either. The fragment consist entirely for the purpose of In App Purchases.
The 3 lines, that the Logcat complains about, doesn't make much sense to me, as they're very different, and doesn't really concern the same things.
Main activity:
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)); } } The troubled fragment:
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 Message:
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)
getFragmentManager()and the deprecated framework Fragments?