0

The dialog frag is being called in the onOptionsItemSelected method. From there, both the date picker and the clear history fragments seem to get null pointers when an sql db is called.

Main activity and dialogFrag class shown below. Stack trace for error at bottom also:

Main Activity:

package com.example.charl.walkthisway;

import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.design.widget.NavigationView;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;


import java.sql.Date;

import Dialogs.ClearHistoryWarning;
import Dialogs.DatePickerTestMode;
import Models.DbManager;
import SystemDateStrategy.SystemDatePreferenceManager;
import Tabs.Goal;
import Tabs.History;
import Tabs.MainTabsLayout;

import static com.example.charl.walkthisway.R.id.stats;

public class MainActivity extends AppCompatActivity
        implements NavigationView.OnNavigationItemSelectedListener, DatePickerTestMode.OnCompleteListener,
        ClearHistoryWarning.OnCompleteListener {

    DbManager db = new DbManager(this, null, null, DbManager.DATABASE_VERSION);
    SystemDatePreferenceManager util = new SystemDatePreferenceManager();

    History history = new History();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        util.mainModeDate(this);

        // Nav drawer!
        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
                this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
        drawer.setDrawerListener(toggle);
        toggle.syncState();

        NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
        navigationView.setNavigationItemSelectedListener(this);

        displaySelectedScreen(R.id.walk);
        db = new DbManager(this, null, null, 2);

    }

    @Override
    public void onBackPressed() {
        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        if (drawer.isDrawerOpen(GravityCompat.START)) {
            drawer.closeDrawer(GravityCompat.START);
        } else {
            super.onBackPressed();
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);

        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        if (item.isChecked()) item.setChecked(false);
        else item.setChecked(true);

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            Intent i = new Intent(this, SettingsPreferences.class);
            startActivity(i);
        }
        if (id == R.id.action_date_picker) {
            FragmentManager fm = getSupportFragmentManager();
            DatePickerTestMode dp = new DatePickerTestMode();
            //dp.setTargetFragment(new Goal(), 0);
            dp.show(fm, "date picker");
        }
        if (id == R.id.action_delete_history) {
            FragmentManager fm = getSupportFragmentManager();
            ClearHistoryWarning chw = new ClearHistoryWarning();
            chw.setTargetFragment(new History(), 0);
            chw.show(fm, "date picker");
        }


        return super.onOptionsItemSelected(item);
    }

    @SuppressWarnings("StatementWithEmptyBody")
    @Override
    public boolean onNavigationItemSelected(MenuItem item) {
        //calling the method displayselectedscreen and passing the id of selected menu
        displaySelectedScreen(item.getItemId());
        return true;
    }

    private void displaySelectedScreen(int itemId) {

        //creating fragment object
        Fragment fragment = null;

        //initializing the fragment object which is selected
        switch (itemId) {
            case R.id.Settings:
                Intent i = new Intent(this, SettingsPreferences.class);
                startActivity(i);
                break;
            case R.id.walk:
                fragment = new MainTabsLayout();
                break;
            case stats:
                fragment = new Goal();
                break;
            case R.id.test:
                fragment = history;
                break;
        }

        /***
         * Use this section to replace the content main with different fragments:
         * remembering that any layouts in content_main will make all frags the
         * the same format
         */
        if (fragment != null) {
            FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
            ft.replace(R.id.content_frame, fragment);
            ft.commit();
        }

        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        drawer.closeDrawer(GravityCompat.START);
    }

    @Override
    public void onComplete(Date boop) {
        Log.d("filter", "some date is: " + String.valueOf(boop));
        util.testModeDate(boop, this);
    }


    @Override
    public void onClearHistory(Boolean clearHistory) {
        if (clearHistory) {
            db.clearHistory();
            clearHistory = false;
        }
    }
}

DatePicker DialogFrag:

   package Dialogs;

import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.DialogFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.DatePicker;
import android.widget.Toast;

import com.example.charl.walkthisway.R;

import Models.DbManager;
import SystemDateStrategy.SystemDateManager;
import SystemDateStrategy.SystemDatePreferenceManager;

import java.sql.Date;
import java.text.SimpleDateFormat;
import java.util.Calendar;


public class DatePickerTestMode extends DialogFragment {
    // TODO: Rename parameter arguments, choose names that match
    // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
    private static final String ARG_PARAM1 = "param1";
    private static final String ARG_PARAM2 = "param2";

    SystemDatePreferenceManager util = new SystemDatePreferenceManager();

    // TODO: Rename and change types of parameters
    private String mParam1;
    private String mParam2;
    String dateString;
    Date someDate;
    private OnCompleteListener completeListener;
    DbManager db = new DbManager(this.getActivity().getApplicationContext(), null, null, DbManager.DATABASE_VERSION);

    public DatePickerTestMode() {
        // Required empty public constructor
    }

    /**
     * Use this factory method to create a new instance of
     * this fragment using the provided parameters.
     *
     * @param param1 Parameter 1.
     * @param param2 Parameter 2.
     * @return A new instance of fragment DatePickerTestMode.
     */
    // TODO: Rename and change types and number of parameters
    public static DatePickerTestMode newInstance(String param1, String param2) {
        DatePickerTestMode fragment = new DatePickerTestMode();
        Bundle args = new Bundle();
        args.putString(ARG_PARAM1, param1);
        args.putString(ARG_PARAM2, param2);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            mParam1 = getArguments().getString(ARG_PARAM1);
            mParam2 = getArguments().getString(ARG_PARAM2);
        }
        setHasOptionsMenu(true);

    }


    @NonNull
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {

        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());

        LayoutInflater inflater = getActivity().getLayoutInflater();
        View v = inflater.inflate(R.layout.fragment_date_picker, null);

        DatePicker datePicker = (DatePicker) v.findViewById(R.id.datePicker);
        Calendar calendar = Calendar.getInstance();

        datePicker.init(calendar.get(Calendar.YEAR),
                calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH),
                new DatePicker.OnDateChangedListener() {
                    @Override
                    public void onDateChanged(DatePicker datePicker, int year, int month, int dayOfMonth) {

                        someDate = new Date(year - 1900, month, dayOfMonth);

                        util.testModeDate(someDate, getContext());

                        SystemDateManager date = new SystemDateManager();
                        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                        // dateString = sdf.format(someDate);
                        dateString = date.systemDateDecider(getContext());
                    }
                });

        db.minStat();


        builder.setView(v).setPositiveButton("Ok", new DialogInterface.OnClickListener() {

            @Override
            public void onClick(DialogInterface dialog, int which) {
                Toast.makeText(getContext(), dateString, Toast.LENGTH_LONG);
                //DbManager db = new DbManager(getContext().getApplicationContext(), null, null, DbManager.DATABASE_VERSION);
                //db.minStat();
                completeListener.onComplete(someDate);
                dismiss();
            }
        }).setNegativeButton("cancel", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                Toast.makeText(getContext(), "dis is cancel", Toast.LENGTH_LONG);
                dismiss();
            }
        });
        return builder.create();
    }


    public static interface OnCompleteListener {
        public abstract void onComplete(Date date);
    }

    // make sure the Activity implemented it


    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        try {
            this.completeListener = (OnCompleteListener) context;
        } catch (final ClassCastException e) {
            throw new ClassCastException(context.toString() + " must implement OnCompleteListener");
        }
    }
}

StackTrace:

 FATAL EXCEPTION: main
                  Process: com.example.charl.Goal, PID: 26338
                  java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.Context android.support.v4.app.FragmentActivity.getApplicationContext()' on a null object reference
                      at Dialogs.DatePickerTestMode.<init>(DatePickerTestMode.java:40)
                      at com.example.charl.walkthisway.MainActivity.onOptionsItemSelected(MainActivity.java:98)
                      at android.app.Activity.onMenuItemSelected(Activity.java:2895)
                      at android.support.v4.app.FragmentActivity.onMenuItemSelected(FragmentActivity.java:406)
                      at android.support.v7.app.AppCompatActivity.onMenuItemSelected(AppCompatActivity.java:195)
                      at android.support.v7.view.WindowCallbackWrapper.onMenuItemSelected(WindowCallbackWrapper.java:103)
                      at android.support.v7.view.WindowCallbackWrapper.onMenuItemSelected(WindowCallbackWrapper.java:103)
                      at android.support.v7.app.ToolbarActionBar$2.onMenuItemClick(ToolbarActionBar.java:69)
                      at android.support.v7.widget.Toolbar$1.onMenuItemClick(Toolbar.java:203)
                      at android.support.v7.widget.ActionMenuView$MenuBuilderCallback.onMenuItemSelected(ActionMenuView.java:762)
                      at android.support.v7.view.menu.MenuBuilder.dispatchMenuItemSelected(MenuBuilder.java:810)
                      at android.support.v7.view.menu.MenuItemImpl.invoke(MenuItemImpl.java:152)
                      at android.support.v7.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:957)
                      at android.support.v7.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:947)
                      at android.support.v7.widget.ActionMenuView.invokeItem(ActionMenuView.java:616)
                      at android.support.v7.view.menu.ActionMenuItemView.onClick(ActionMenuItemView.java:153)
                      at android.view.View.performClick(View.java:4785)
                      at android.view.View$PerformClick.run(View.java:19884)
                      at android.os.Handler.handleCallback(Handler.java:746)
                      at android.os.Handler.dispatchMessage(Handler.java:95)
                      at android.os.Looper.loop(Looper.java:135)
                      at android.app.ActivityThread.main(ActivityThread.java:5343)
                      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:905)
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:700)
Application terminated.
  • post this file - DatePickerTestMode.java line 40 over there is where the error is happening – Shmuel Mar 19 '17 at 23:55
  • btw, thats how you read this logcat - java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.Context android.support.v4.app.FragmentActivity.getApplicationContext()' on a null object reference at Dialogs.DatePickerTestMode.(DatePickerTestMode.java:40) – Shmuel Mar 19 '17 at 23:55
  • @shmuel posted datepicker dialog frag. It shows the error is at: DbManager db = new DbManager(this.getActivity().getApplicationContext(), null, null, DbManager.DATABASE_VERSION); I have tried using different context such as getContext() and getActivity() etc but none of them work so I think I am doing something more or less logically wrong here. – Charlotte A.Wilson Mar 20 '17 at 00:07

3 Answers3

0

DbManager db = new DbManager(this.getActivity().getApplicationContext(), null, null, DbManager.DATABASE_VERSION);

is the error. You can't call this.getActivity().getApplicationContext() before a fragment is attached

Shmuel
  • 3,916
  • 2
  • 27
  • 45
0

For anyone else untrained in the art of knowing how to work android, I have a massive workaround:

Since you can't call getActivity before fragment is attached I just used the onOptionsItemSelected method override in another fragment I had:

@Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();

        if (id == R.id.action_delete_history) {

            FragmentManager fm = getFragmentManager();
            ClearHistoryWarning clear = new ClearHistoryWarning();
            clear.setTargetFragment(History.this, 0);
            clear.show(fm, "Add New Goal");
        }
        return super.onOptionsItemSelected(item);
    }

On activity result from this:

    @Override
        public void onActivityResult(int requestCode, int resultCode, Intent data) {
            if (resultCode == 0) {
                DbManager dbd = new DbManager(this.getActivity().getApplicationContext(), null, null, DbManager.DATABASE_VERSION);
                dbd.clearHistory();
                populateListView();
            }
            super.onActivityResult(requestCode, resultCode, data);
        }

Where populateListView() just populates a cursorAdapter from the db.

Not forgetting to use:

    setHasOptionsMenu(true);

In the onCreateMethod.

From the Dialog Frag, just before the dismiss I have:

     getTargetFragment().onActivityResult(getTargetRequestCode(), 0, getActivity().getIntent());

Previous Implementation:

My previous implementation was to use an interface and have that take in a boolean value when the history button was clicked then send that to the main activity to clear the db from its implementation of the interface method. But this didn't let me update the view in my fragment straight away as I had to swipe left a couple times and come back ( using tablayout and viewpager) for the onResume() method to call and subsequently call my populateListView method.

  • Alternatively, you can just initialize the variable in `onCreate()`. – Code-Apprentice Mar 20 '17 at 00:45
  • Also, you should not call `onActivityResult()` directly. This callback is intended for use by the Android system when used correctly. If you are not using `startActivityForResult()`, then you should just write a method with a name that you choose yourself. – Code-Apprentice Mar 20 '17 at 00:54
  • @Code-Apprentice thanks for the info. I tried initalizing in the onCreate() and it wasn't working. What should I use instead of onActivityResult? Previous implementation described in code edit ^ Never mind, I see you have commented with some code as well. Thanks again! – Charlotte A.Wilson Mar 20 '17 at 01:11
0

You should initialize your database helper in onCreate():

public class DatePickerTestMode extends DialogFragment {

    private DbManager db;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        db = new DbManager(getActivity(), null, null, DbManager.DATABASE_VERSION);

        setHasOptionsMenu(true);

    }
}

Note that I used getActivity() since an Activity is a Context. This is preferred unless you have a specific reason to use the application context.

Code-Apprentice
  • 81,660
  • 23
  • 145
  • 268