Crashing on clicking on a list item


#1

Please help me with this. I started this project but had to take a break and now when I tried to implement TimePickerFragment my app keeps crashing when I click on an item in list.

Crime.java

package com.example.flame.criminalintent;

import java.util.Date;
import java.util.UUID;

/**

  • Created by FlaMe on 6/10/2017.
    */

public class Crime {

private UUID mId;
private String mTitle;
private boolean mSolved;
private Date mDate;

public void setmTime(Date mTime) {
    this.mTime = mTime;
}

public Date getmTime() {
    return mTime;
}

private Date mTime;


public Date getmDate() {
    return mDate;
}

public boolean ismSolved() {
    return mSolved;
}

public void setmDate(Date mDate) {
    this.mDate = mDate;
}

public void setmSolved(boolean mSolved) {
    this.mSolved = mSolved;
}

public Crime()
{
    mId=UUID.randomUUID();
    mDate = new Date();
}

@Override
public String toString() {
    return mTitle;
}

public UUID getmId() {
    return mId;
}

public void setmTitle(String mTitle) {
    this.mTitle = mTitle;
}

public String getmTitle() {
    return mTitle;
}

}

CrimeFragment.java

package com.example.flame.criminalintent;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.text.Editable;
import android.text.TextWatcher;
import android.text.format.DateFormat;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;

import java.util.Date;
import java.util.UUID;

/**

  • Created by FlaMe on 6/10/2017.
    */

public class CrimeFragment extends Fragment {
private Crime mCrime;
private EditText mTitleField;
private Button mDateButton;
private Button mTimeButton;
private CheckBox mSolvedCheckBox;
public static final String EXTRA_CRIME_ID=“com.example.flame.android.criminalintent.crime_id”;
private static final String DIALOG_DATE = “DialogDate”;
public static final int REQUEST_DATE = 0;
private static final String DIALOG_TIME = “DialogTime”;
public static final int REQUEST_TIME = 0;

android.text.format.DateFormat df = new android.text.format.DateFormat();
public void updateDate()
{
    mDateButton.setText(DateFormat.format("EEE MMM dd yyyy", mCrime.getmDate()));
}
private void updateTime() {
    mTimeButton.setText(DateFormat.format("hh:mm a z", mCrime.getmTime()));
}

@Override
public void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    UUID crimeId = (UUID)getArguments().getSerializable(EXTRA_CRIME_ID);
    mCrime = CrimeLab.get(getActivity()).getCrime(crimeId);
}

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

    mTitleField =  (EditText)v.findViewById(R.id.crime_title);
    mTitleField.setText(mCrime.getmTitle());
    mTitleField.addTextChangedListener(new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence c, int start, int count, int after) {

        }

        @Override
        public void onTextChanged(CharSequence c, int start, int before, int count) {
            mCrime.setmTitle(c.toString());
        }

        @Override
        public void afterTextChanged(Editable c) {

        }
    });

    mDateButton = (Button)v.findViewById(R.id.crime_date);
    updateDate();
    mDateButton.setOnClickListener(new View.OnClickListener() {
        public void onClick(View v) {
            FragmentManager fm = getActivity()
                    .getSupportFragmentManager();
            DatePickerFragment dialog = DatePickerFragment.newInstance(mCrime.getmDate());
            dialog.setTargetFragment(CrimeFragment.this, REQUEST_DATE);
            dialog.show(fm, DIALOG_DATE);
        }
    });

    mTimeButton = (Button)v.findViewById(R.id.crime_time);
    updateTime();
    mTimeButton.setOnClickListener(new View.OnClickListener(){
        public void onClick(View v) {
            FragmentManager fm2 = getActivity()
                    .getSupportFragmentManager();
            TimePickerFragment dialog2 = TimePickerFragment.newInstance(mCrime.getmTime());
            dialog2.setTargetFragment(CrimeFragment.this, REQUEST_TIME);
            dialog2.show(fm2, DIALOG_TIME);
        }
    });


            mSolvedCheckBox = (CheckBox) v.findViewById(R.id.crime_solved);
    mSolvedCheckBox.setChecked(mCrime.ismSolved());
    mSolvedCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
            mCrime.setmSolved(isChecked);
        }
    });

    return v;
}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data){
    if(resultCode!= Activity.RESULT_OK)
        return;

    if(requestCode==REQUEST_DATE) {
        Date date = (Date) data
                .getSerializableExtra(DatePickerFragment.EXTRA_DATE);
        mCrime.setmDate(date);
        updateDate();
    }

    if(requestCode==REQUEST_TIME){
        Date time = (Date)data
                .getSerializableExtra(TimePickerFragment.EXTRA_TIME);
        mCrime.setmTime(time);
        updateTime();
    }

}

public static CrimeFragment newInstance(UUID crimeId){
    Bundle args=new Bundle();
    args.putSerializable(EXTRA_CRIME_ID,crimeId);
    CrimeFragment fragment = new CrimeFragment();
    fragment.setArguments(args);
    return fragment;
}

}

CrimeLab.java

package com.example.flame.criminalintent;

import android.content.Context;

import java.util.ArrayList;
import java.util.UUID;

/**

  • Created by FlaMe on 6/13/2017.
    */

public class CrimeLab {

private ArrayList<Crime> mCrimes;
private static CrimeLab sCrimeLab;
private Context mAppContext;

private CrimeLab(Context appContext) {
    mAppContext = appContext;
    mCrimes = new ArrayList<Crime>();
    for(int i=0;i<100;i++)
    {
        Crime c =  new Crime();
        c.setmTitle("Crime #"+i);
        c.setmSolved(i%2==0);
        mCrimes.add(c);
    }
}

public static CrimeLab get(Context c) {
    if(sCrimeLab==null)
        sCrimeLab= new CrimeLab(c.getApplicationContext());
    return sCrimeLab;
}

public ArrayList<Crime> getCrimes() {
    return mCrimes;
}

public Crime getCrime(UUID id)
{
    for(Crime c : mCrimes)
    {
        if(c.getmId().equals(id))
            return c;
    }
    return null;
}

}
[/details][details=CrimeListActivity.java]package com.example.flame.criminalintent;

import android.support.v4.app.Fragment;

/**

  • Created by FlaMe on 6/13/2017.
    */

public class CrimeListActivity extends SingleFragmentActivity {

@Override
protected Fragment createFragment() {
return new CrimeListFragment();
}

}
[/details][details=CrimeListFragment.java]
package com.example.flame.criminalintent;

import android.support.v4.app.ListFragment;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.ListView;
import android.widget.TextView;

import java.util.ArrayList;

/**

  • Created by FlaMe on 6/13/2017.
    */

public class CrimeListFragment extends ListFragment {

private ArrayList<Crime> mCrimes;
private static final String TAG = "CrimeListFragment";
android.text.format.DateFormat df = new android.text.format.DateFormat();

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    getActivity().setTitle(R.string.crimes_title);
    mCrimes = CrimeLab.get(getActivity()).getCrimes();

    CrimeAdapter adapter = new CrimeAdapter(mCrimes);
    setListAdapter(adapter);


}

@Override
public void onListItemClick(ListView l, View v, int position, long id) {
    Crime c = ((CrimeAdapter) getListAdapter()).getItem(position);
    Intent i =new Intent(getActivity(),CrimePagerActivity.class);
    i.putExtra(CrimeFragment.EXTRA_CRIME_ID,c.getmId());
    startActivity(i);
}

private class CrimeAdapter extends ArrayAdapter<Crime> {
    public CrimeAdapter(ArrayList<Crime> crimes) {
        super(getActivity(), 0, crimes);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if (convertView == null) {
            convertView = getActivity().getLayoutInflater()
                    .inflate(R.layout.list_item_crime, null);
        }
        Crime c = getItem(position);

        TextView titleTextView =
                (TextView) convertView.findViewById(R.id.crime_list_item_titleTextView);
        titleTextView.setText(c.getmTitle());

        TextView dateTextView =
                (TextView) convertView.findViewById(R.id.crime_list_item_dateTextView);
        dateTextView.setText(df.format("EEE MMM dd yyyy", c.getmDate()));

        CheckBox solvedCheckBox =
                (CheckBox) convertView.findViewById(R.id.crime_list_item_solvedCheckBox);
        solvedCheckBox.setChecked(c.ismSolved());

        return convertView;
    }


}

@Override
public void onResume()
{
    super.onResume();
    ((CrimeAdapter)getListAdapter()).notifyDataSetChanged();
}

}
[/details][details=CrimePagerActivity.java]
package com.example.flame.criminalintent;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.ActionBarActivity;

import java.util.ArrayList;
import java.util.UUID;

/**

  • Created by FlaMe on 6/13/2017.
    */

public class CrimePagerActivity extends ActionBarActivity {

private ViewPager mViewPager;
private ArrayList<Crime> mCrimes;

@Override
public void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    mViewPager=new ViewPager(this);
    mViewPager.setId(R.id.viewPager);
    setContentView(mViewPager);

    mCrimes = CrimeLab.get(this).getCrimes();

    FragmentManager fm = getSupportFragmentManager();
    mViewPager.setAdapter(new FragmentStatePagerAdapter(fm) {
        @Override
        public Fragment getItem(int position) {
            Crime crime = mCrimes.get(position);
            return CrimeFragment.newInstance(crime.getmId());
        }

        @Override
        public int getCount() {
            return mCrimes.size();
        }
    });

    mViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
        public void onPageScrollStateChanged(int state){
        }
        public void onPageScrolled(int pos, float posOffset, int posOffsetPixels) {}
        public void onPageSelected(int pos) {
            Crime crime = mCrimes.get(pos);
            if (crime.getmTitle() != null) {
                setTitle(crime.getmTitle());
            }
        }
    });

    UUID crimeId = (UUID)getIntent()
            .getSerializableExtra(CrimeFragment.EXTRA_CRIME_ID);
    for(int i = 0; i<mCrimes.size();i++)
    {
        if(mCrimes.get(i).getmId().equals(crimeId))
        {
            mViewPager.setCurrentItem(i);
            break;
        }
    }
}

}

DatePickerFragment.java

package com.example.flame.criminalintent;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.icu.util.GregorianCalendar;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.DatePicker;

import java.util.Calendar;
import java.util.Date;

/**

  • Created by FlaMe on 6/14/2017.
    */

public class DatePickerFragment extends DialogFragment {
public static final String ARG_DATE = “date”;
public static final String EXTRA_DATE =
“com.example.flame.criminalintent.date”;
private DatePicker mDatePicker;

public static DatePickerFragment newInstance(Date date) {
    Bundle args = new Bundle();
    args.putSerializable(ARG_DATE, date);

    DatePickerFragment fragment = new DatePickerFragment();
    fragment.setArguments(args);
    return fragment;
}


@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {

    Date date = (Date) getArguments().getSerializable(ARG_DATE);

    Calendar calendar = Calendar.getInstance();
    calendar.setTime(date);
    int year = calendar.get(Calendar.YEAR);
    int month = calendar.get(Calendar.MONTH);
    int day = calendar.get(Calendar.DAY_OF_MONTH);

    View v = LayoutInflater.from(getActivity()).inflate(R.layout.dialog_date, null);

    mDatePicker = (DatePicker)v.findViewById(R.id.dialog_date_datePicker);
    mDatePicker.init(year,month,day, null);

    return new AlertDialog.Builder(getActivity())
            .setView(v)
            .setTitle(R.string.date_picker_title)
            .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    int year =
                            mDatePicker.getYear();
                    int month =
                            mDatePicker.getMonth();
                    int day =
                            mDatePicker.getDayOfMonth();
                    Date date = new
                            GregorianCalendar(year, month, day).getTime();
                    sendResult(Activity.RESULT_OK, date);
                }
            })
            .create();
}

private void sendResult(int resultCode, Date date){
    if(getTargetFragment()==null)
        return;
    Intent i =  new Intent();
    i.putExtra(EXTRA_DATE, date);
    getTargetFragment().onActivityResult(getTargetRequestCode(), resultCode, i);
}

}
[/details][details=SingleFragmentActivity.java]
package com.example.flame.criminalintent;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v7.app.ActionBarActivity;

/**

  • Created by FlaMe on 6/13/2017.
    */

public abstract class SingleFragmentActivity extends ActionBarActivity {
protected abstract Fragment createFragment();

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_fragment);

    FragmentManager fm =getSupportFragmentManager();
    Fragment fragment = fm.findFragmentById(R.id.fragmentContainer);

    if(fragment==null)
    {
        fragment =  createFragment();
        fm.beginTransaction()
                .add(R.id.fragmentContainer, fragment)
                .commit();
    }
}

}
[/details][details=TimePickerFragment.java]
package com.example.flame.criminalintent;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TimePicker;

import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

/**

  • Created by FlaMe on 6/23/2017.
    */

public class TimePickerFragment extends DialogFragment {
public static final String ARG_TIME = “time”;
public static final String EXTRA_TIME =
“com.example.flame.criminalintent.time”;
private Date time;
private TimePicker mTimePicker;
private int hour, minute;

public static TimePickerFragment newInstance(Date time){
    Bundle args = new Bundle();
    args.putSerializable(ARG_TIME, time);

    TimePickerFragment fm = new TimePickerFragment();
    fm.setArguments(args);
    return fm;
}

@Override
public Dialog onCreateDialog(Bundle savedInstanceState)
{
    time = (Date)getArguments().getSerializable(ARG_TIME);

    Calendar calendar = Calendar.getInstance();
    calendar.setTime(time);
    hour = calendar.get(Calendar.HOUR_OF_DAY);
    minute = calendar.get(Calendar.MINUTE);

    View v  = LayoutInflater.from(getActivity()).inflate(R.layout.dialog_time, null);

    mTimePicker = (TimePicker)v.findViewById(R.id.dialog_time_picker);
    if (Build.VERSION.SDK_INT >= 23 ) {
        mTimePicker.setHour(hour);
        mTimePicker.setMinute(minute);
    }
    else {
        mTimePicker.setCurrentHour(hour);
        mTimePicker.setCurrentMinute(minute);
    }

    mTimePicker.setOnTimeChangedListener(new TimePicker.OnTimeChangedListener() {

        @Override
        public void onTimeChanged(TimePicker view, int hour, int minute) {
            final Calendar cal = Calendar.getInstance();
            cal.setTime(time);
            int year = cal.get(Calendar.YEAR);
            int monthOfYear = cal.get(Calendar.MONTH);
            int dayOfMonth = cal.get(Calendar.DAY_OF_MONTH);

            time = new GregorianCalendar(year, monthOfYear, dayOfMonth, hour, minute).getTime();

            // Update argument to preserve selected value on rotation
            getArguments().putSerializable(EXTRA_TIME, time);
        }
    });

    return new AlertDialog.Builder(getActivity())
        .setView(v)
            .setTitle(R.string.time_picker_title)
            .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener(){
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    sendResult(Activity.RESULT_OK, time);
                }
            })
            .create();
}
private void sendResult(int resultCode, Date time) {
    if (getTargetFragment() == null)
        return;

    Intent intent = new Intent();
    intent.putExtra(EXTRA_TIME, time);
    getTargetFragment().onActivityResult(getTargetRequestCode(), resultCode, intent);
}

}


#2

When you see a crash, start by looking at the stacktrace in logcat. Follow the steps from the debugging chapter to help you track down the problem.

I will help if you post here, but try to fix the problem yourself first.


#3

Thank! I’ll get on it soon and will let you know if I can’t figure out the problem


#4

am having the same issue when i try to add
View v = LayoutInflater.from(getActicity()).inflate(R.layout.dialog_date, null); on page 233


#5

Take a look at the logs to see what caused the crash. Feel free to post them here and I can help out.


#6

06-12 14:32:49.614 2958-2978/com.bignerdranch.android.criminalintent E/OpenGLRenderer: GL error: 0x506
06-12 14:32:49.615 2958-2978/com.bignerdranch.android.criminalintent A/OpenGLRenderer: GL errors! frameworks/base/libs/hwui/renderthread/CanvasContext.cpp:505
06-12 14:32:49.615 2958-2978/com.bignerdranch.android.criminalintent A/libc: Fatal signal 6 (SIGABRT), code -6 in tid 2978 (RenderThread)
06-12 14:32:49.651 3965-3965/? A/DEBUG: *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
Build fingerprint: ‘google/sdk_google_phone_x86/generic_x86:7.0/NYC/4409132:user/release-keys’
Revision: ‘0’
ABI: ‘x86’
06-12 14:32:49.653 3965-3965/? A/DEBUG: pid: 2958, tid: 2978, name: RenderThread >>> com.bignerdranch.android.criminalintent <<<
signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
06-12 14:32:49.655 3965-3965/? A/DEBUG: Abort message: ‘GL errors! frameworks/base/libs/hwui/renderthread/CanvasContext.cpp:505’
eax 00000000 ebx 00000b8e ecx 00000ba2 edx 00000006
esi 94ffb978 edi 94ffb920
xcs 00000073 xds 0000007b xes 0000007b xfs 0000003b xss 0000007b
eip b171c424 ebp 94ffad88 esp 94ffad2c flags 00000292
06-12 14:32:49.660 3965-3965/? A/DEBUG: backtrace:
#00 pc ffffe424 [vdso:b171c000] (__kernel_vsyscall+16)
#01 pc 0007a00c /system/lib/libc.so (tgkill+28)
#02 pc 00075855 /system/lib/libc.so (pthread_kill+85)
#03 pc 0002782a /system/lib/libc.so (raise+42)
#04 pc 0001ee06 /system/lib/libc.so (abort+86)
06-12 14:32:49.661 3965-3965/? A/DEBUG: #05 pc 0000fd55 /system/lib/libcutils.so (__android_log_assert+245)
#06 pc 0002aa51 /system/lib/libhwui.so
#07 pc 0002daa1 /system/lib/libhwui.so
#08 pc 00033d7d /system/lib/libhwui.so (_ZN7android10uirenderer12renderthread12RenderThread10threadLoopEv+189)
#09 pc 00012085 /system/lib/libutils.so (_ZN7android6Thread11_threadLoopEPv+309)
#10 pc 0006f60b /system/lib/libandroid_runtime.so (_ZN7android14AndroidRuntime15javaThreadShellEPv+111)
#11 pc 00011873 /system/lib/libutils.so (ZN13thread_data_t10trampolineEPKS+259)
#12 pc 00074fb2 /system/lib/libc.so (_ZL15__pthread_startPv+210)
#13 pc 0002026e /system/lib/libc.so (__start_thread+30)
#14 pc 0001e046 /system/lib/libc.so (__bionic_clone+70)


#7

I changed from the emulator to an actual device and the code runs fine


#8

Thank you for following up with your solution.

That crash is certainly strange. It’s a crash in Android’s native code so you don’t get much of a stacktrace (that’s useful anyway). Those types of crashes are rare and could be related to your code, but more likely it’s a bug in the OS (or the emulator) itself.

In this case, my best guess is that there’s some problem with the emulator and not your code. I’d expect that you won’t see this on any real device.