The Problem: When starting an activity for result in CreateCourse.java, the app will crash.
Error Message:
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.nbdeg.unityplanner/com.nbdeg.unityplanner.Utils.CourseAddTime}: android.view.InflateException: Binary XML file line #103: Attempt to invoke virtual method 'boolean java.lang.String.equals(java.lang.Object)' on a null object reference
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2665)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2726)
at android.app.ActivityThread.-wrap12(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1477)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6119)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
Caused by: android.view.InflateException: Binary XML file line #103: Attempt to invoke virtual method 'boolean java.lang.String.equals(java.lang.Object)' on a null object reference
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.lang.String.equals(java.lang.Object)' on a null object reference
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:761)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:727)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:858)
at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:821)
at android.view.LayoutInflater.inflate(LayoutInflater.java:518)
at android.view.LayoutInflater.inflate(LayoutInflater.java:426)
at android.view.LayoutInflater.inflate(LayoutInflater.java:377)
at com.android.internal.policy.PhoneWindow.setContentView(PhoneWindow.java:412)
at android.app.Activity.setContentView(Activity.java:2414)
at com.nbdeg.unityplanner.Utils.CourseAddTime.onCreate(CourseAddTime.java:43)
at android.app.Activity.performCreate(Activity.java:6679)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2618)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2726)
at android.app.ActivityThread.-wrap12(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1477)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6119)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
What I've tried: Adding android.permission.WRITE_EXTERNAL_STORAGE and android.permission.READ_EXTERNAL_STORAGE and changing request code.
If anyone has any idea of what's happening or how I can fix it, it would be much appreciated.
Classes:
CreateCourse.java (the class calling startActivityForResult)
package com.nbdeg.unityplanner;
import android.app.Activity;
import android.content.Intent;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential;
import com.google.api.client.util.ExponentialBackOff;
import com.google.firebase.auth.UserInfo;
import com.nbdeg.unityplanner.Data.Course;
import com.nbdeg.unityplanner.Data.Time;
import com.nbdeg.unityplanner.Utils.CourseAddTime;
import com.nbdeg.unityplanner.Utils.Database;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import eltos.simpledialogfragment.SimpleDialog;
import eltos.simpledialogfragment.color.SimpleColorDialog;
import pub.devrel.easypermissions.AfterPermissionGranted;
import pub.devrel.easypermissions.EasyPermissions;
import static com.nbdeg.unityplanner.Dashboard.REQUEST_PERMISSION_GET_ACCOUNTS;
public class CreateCourse extends AppCompatActivity implements SimpleDialog.OnDialogResultListener {
private static final int COURSE_GET_TIME = 1050;
private GoogleAccountCredential gCredential;
private Time time;
private View viewColor;
private Button viewAddTime;
private TextView viewCourseTime;
private EditText viewCourseName;
private EditText viewCourseTeacher;
private EditText viewCourseRoomNumber;
private EditText viewCourseDescription;
final static private String COLOR_DIALOG = "colorDialog";
static private int courseColor;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_create_course);
Button colorSelector = (Button) findViewById(R.id.course_create_button);
viewAddTime = (Button) findViewById(R.id.course_create_add_time);
viewCourseTime = (TextView) findViewById(R.id.course_create_time);
viewColor = findViewById(R.id.course_create_view_color);
viewCourseName = (EditText) findViewById(R.id.course_create_name);
viewCourseTeacher = (EditText) findViewById(R.id.course_create_teacher);
viewCourseRoomNumber = (EditText) findViewById(R.id.course_create_room_number);
viewCourseDescription = (EditText) findViewById(R.id.course_create_description);
courseColor = getMatColor("200");
viewColor.setBackgroundColor(courseColor);
colorSelector.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
SimpleColorDialog.build()
.title("Pick a course color")
.allowCustom(true)
.show(CreateCourse.this, COLOR_DIALOG);
}
});
viewCourseTime.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(CreateCourse.this, CourseAddTime.class);
startActivityForResult(intent, COURSE_GET_TIME);
}
});
viewAddTime.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(CreateCourse.this, CourseAddTime.class);
startActivityForResult(intent, COURSE_GET_TIME);
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == COURSE_GET_TIME) {
if (resultCode == Activity.RESULT_OK) {
SimpleDateFormat formatter = new SimpleDateFormat("h:mm a", java.util.Locale.getDefault());
time = (Time) data.getSerializableExtra("time");
viewAddTime.setVisibility(View.GONE);
if (time.isBlockSchedule()) {
viewCourseTime.setText("A/B Schedule");
} else {
viewCourseTime.setText("Per Day Schedule");
}
viewCourseTime.append("; " + formatter.format(new Date(time.getStartLong())) + " - " + formatter.format(new Date(time.getEndLong())));
viewCourseTime.setVisibility(View.VISIBLE);
} else if (resultCode == Activity.RESULT_CANCELED) {
viewAddTime.setVisibility(View.VISIBLE);
viewCourseTime.setVisibility(View.GONE);
}
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.save, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Save course
Course course = new Course();
if (time == null) {
Toast.makeText(this, "A time is needed", Toast.LENGTH_SHORT).show();
return super.onOptionsItemSelected(item);
}
if (viewCourseName.getText().toString().equals("")) {
Toast.makeText(this, "A course name is needed", Toast.LENGTH_SHORT).show();
return super.onOptionsItemSelected(item);
} else {
course.setName(viewCourseName.getText().toString());
}
if (viewCourseTeacher.getText().toString().equals("")) {
Toast.makeText(this, "A teacher is needed", Toast.LENGTH_SHORT).show();
return super.onOptionsItemSelected(item);
} else {
course.setTeacher(viewCourseTeacher.getText().toString());
}
course.setRoomNumber(viewCourseRoomNumber.getText().toString());
course.setDescription(viewCourseDescription.getText().toString());
course.setColor(courseColor);
for (UserInfo info : Database.getUser().getProviderData()) {
if (info.getProviderId().equals("google.com")) {
if (EasyPermissions.hasPermissions(this, android.Manifest.permission.GET_ACCOUNTS)) {
signInGoogleCredential();
return super.onOptionsItemSelected(item);
} else {
EasyPermissions.requestPermissions(
this,
"This app needs to access your Google account (via Contacts).",
REQUEST_PERMISSION_GET_ACCOUNTS,
android.Manifest.permission.GET_ACCOUNTS);
}
}
}
if (time.isBlockSchedule()) {
try {
course.setTime(Database.createEventByBlock(this, gCredential, course.getName(), time.getStartLong(), time.getEndLong(), time.getFinish()));
} catch (IOException e) {
e.printStackTrace();
}
} else if (time.isDaySchedule()) {
try {
course.setTime(Database.createEventByDay(this, gCredential, course.getName(), time.getDays(), time.getStartLong(), time.getEndLong(), time.getFinish()));
} catch (IOException e) {
e.printStackTrace();
}
}
Database.createCourse(course);
return super.onOptionsItemSelected(item);
}
private int getMatColor(String typeColor) {
int returnColor = Color.BLACK;
int arrayId = getResources().getIdentifier("mdcolor_" + typeColor, "array", getApplicationContext().getPackageName());
if (arrayId != 0)
{
TypedArray colors = getResources().obtainTypedArray(arrayId);
int index = (int) (Math.random() * colors.length());
returnColor = colors.getColor(index, Color.BLACK);
colors.recycle();
}
return returnColor;
}
@Override
public boolean onResult(@NonNull String dialogTag, int which, @NonNull Bundle extras) {
if (dialogTag.equals(COLOR_DIALOG)) {
courseColor = extras.getInt(SimpleColorDialog.COLOR);
viewColor.setBackgroundColor(courseColor);
return true;
}
return false;
}
@AfterPermissionGranted(REQUEST_PERMISSION_GET_ACCOUNTS)
private void signInGoogleCredential() {
gCredential = GoogleAccountCredential.usingOAuth2(
this, Arrays.asList(LauncherLogin.SCOPES))
.setBackOff(new ExponentialBackOff());
gCredential.setSelectedAccountName(Database.getUser().getEmail());
}
}
CourseAddTime.java (the started Activity):
package com.nbdeg.unityplanner.Utils;
import android.app.Activity;
import android.app.TimePickerDialog;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.RadioButton;
import android.widget.RelativeLayout;
import android.widget.TimePicker;
import android.widget.Toast;
import com.nbdeg.unityplanner.Data.Time;
import com.nbdeg.unityplanner.R;
import java.util.Calendar;
public class CourseAddTime extends Activity {
private int startHour;
private int startMin;
private int endHour;
private int endMin;
private EditTextDatePicker viewStartDate;
private EditTextDatePicker viewStopDate;
private RadioButton viewBlockSchedule;
private RadioButton viewDaySchedule;
private CheckBox viewDayMon;
private CheckBox viewDayTue;
private CheckBox viewDayWen;
private CheckBox viewDayThu;
private CheckBox viewDayFri;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_course_add_time);
final EditText viewStartTime = (EditText) findViewById(R.id.course_add_time_start_time);
final EditText viewEndTime = (EditText) findViewById(R.id.course_add_time_stop_time);
viewStartDate = new EditTextDatePicker(this, R.id.course_add_time_start_date);
viewStopDate = new EditTextDatePicker(this, R.id.course_add_time_stop_date);
viewBlockSchedule = (RadioButton) findViewById(R.id.course_add_time_ab_schedule);
viewDaySchedule = (RadioButton) findViewById(R.id.course_add_time_per_day_schedule);
final RelativeLayout layoutBlockSchedule = (RelativeLayout) findViewById(R.id.course_add_time_ab_schedule_layout);
final LinearLayout layoutDaySchedule = (LinearLayout) findViewById(R.id.course_add_time_per_day_schedule_layout);
viewDayMon = (CheckBox) findViewById(R.id.course_add_time_per_day_schedule_mon);
viewDayTue = (CheckBox) findViewById(R.id.course_add_time_per_day_schedule_tue);
viewDayWen = (CheckBox) findViewById(R.id.course_add_time_per_day_schedule_wen);
viewDayThu = (CheckBox) findViewById(R.id.course_add_time_per_day_schedule_thu);
viewDayFri = (CheckBox) findViewById(R.id.course_add_time_per_day_schedule_fri);
viewStartTime.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Calendar mcurrentTime = Calendar.getInstance();
int hour = mcurrentTime.get(Calendar.HOUR_OF_DAY);
int minute = mcurrentTime.get(Calendar.MINUTE);
TimePickerDialog mTimePicker;
mTimePicker = new TimePickerDialog(CourseAddTime.this, new TimePickerDialog.OnTimeSetListener() {
@Override
public void onTimeSet(TimePicker timePicker, int selectedHour, int selectedMinute) {
viewStartTime.setText( selectedHour + ":" + selectedMinute);
startHour = selectedHour;
startMin = selectedMinute;
}
}, hour, minute, true);
mTimePicker.setTitle("Select Time");
mTimePicker.show();
}
});
viewEndTime.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Calendar mcurrentTime = Calendar.getInstance();
int hour = mcurrentTime.get(Calendar.HOUR_OF_DAY);
int minute = mcurrentTime.get(Calendar.MINUTE);
TimePickerDialog mTimePicker;
mTimePicker = new TimePickerDialog(CourseAddTime.this, new TimePickerDialog.OnTimeSetListener() {
@Override
public void onTimeSet(TimePicker timePicker, int selectedHour, int selectedMinute) {
viewEndTime.setText( selectedHour + ":" + selectedMinute);
endHour = selectedHour;
endMin = selectedMinute;
}
}, hour, minute, true);
mTimePicker.setTitle("Select Time");
mTimePicker.show();
}
});
viewBlockSchedule.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
viewBlockSchedule.setChecked(true);
viewDaySchedule.setChecked(false);
layoutBlockSchedule.setVisibility(View.VISIBLE);
layoutDaySchedule.setVisibility(View.GONE);
}
});
viewDaySchedule.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
viewBlockSchedule.setChecked(true);
viewDaySchedule.setChecked(false);
layoutBlockSchedule.setVisibility(View.GONE);
layoutDaySchedule.setVisibility(View.VISIBLE);
}
});
}
@Override
public void onBackPressed() {
super.onBackPressed();
if (viewStartDate.date == null || viewStopDate.date == null) {
Toast.makeText(this, "No time was added", Toast.LENGTH_SHORT).show();
Intent returnIntent = new Intent();
setResult(Activity.RESULT_CANCELED, returnIntent);
finish();
}
Time courseTime = null;
if (viewBlockSchedule.isChecked()) {
// Block Schedule
Calendar startCal = Calendar.getInstance();
Calendar endCal = Calendar.getInstance();
startCal.setTime(viewStartDate.date);
startCal.set(Calendar.HOUR_OF_DAY, startHour);
startCal.set(Calendar.MINUTE, startMin);
endCal.setTime(viewStartDate.date);
endCal.set(Calendar.HOUR_OF_DAY, endHour);
endCal.set(Calendar.MINUTE, endMin);
courseTime = new Time(null, startCal.getTimeInMillis(), endCal.getTimeInMillis(), viewStopDate.date.getTime());
} else if (viewDaySchedule.isChecked()) {
// Day Schedule
Calendar startCal = Calendar.getInstance();
Calendar endCal = Calendar.getInstance();
startCal.setTime(viewStartDate.date);
startCal.set(Calendar.HOUR_OF_DAY, startHour);
startCal.set(Calendar.MINUTE, startMin);
endCal.setTime(viewStartDate.date);
endCal.set(Calendar.HOUR_OF_DAY, endHour);
endCal.set(Calendar.MINUTE, endMin);
StringBuilder dayBuilder = new StringBuilder();
if (viewDayMon.isChecked()) {
dayBuilder.append("MON,");
}
if (viewDayTue.isChecked()) {
dayBuilder.append("TUE,");
}
if (viewDayWen.isChecked()) {
dayBuilder.append("WEN,");
}
if (viewDayThu.isChecked()) {
dayBuilder.append("THU,");
}
if (viewDayFri.isChecked()) {
dayBuilder.append("FRI,");
}
if (dayBuilder.toString().equals("")) {
Toast.makeText(this, "No time was added", Toast.LENGTH_SHORT).show();
Intent returnIntent = new Intent();
setResult(Activity.RESULT_CANCELED, returnIntent);
finish();
} else {
dayBuilder.deleteCharAt(dayBuilder.length());
dayBuilder.append(";");
}
courseTime = new Time(dayBuilder.toString(), startCal.getTimeInMillis(), endCal.getTimeInMillis(), viewStopDate.date.getTime());
}
Intent returnIntent = new Intent();
returnIntent.putExtra("time", courseTime);
setResult(Activity.RESULT_OK,returnIntent);
finish();
}
}