-3

I got crashed when i click Confirm button and this form my logcat:

2020-01-30 15:11:22.363 5563-5563/com.example.barberbooking E/AndroidRuntime: FATAL EXCEPTION: main Process: com.example.barberbooking, PID: 5563 java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String com.example.barberbooking.Model.Salon.getSalonId()' on a null object reference at com.example.barberbooking.Fragments.BookingStep4Fragment.lambda$null$0$BookingStep4Fragment(BookingStep4Fragment.java:260) at com.example.barberbooking.Fragments.-$$Lambda$BookingStep4Fragment$4Ef790x-NNkmXHs_bv2YFCA2Nyk.onSuccess(Unknown Source:4) at com.google.android.gms.tasks.zzn.run(Unknown Source:4) at android.os.Handler.handleCallback(Handler.java:790) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:164) at android.app.ActivityThread.main(ActivityThread.java:6494) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)


package com.example.barberbooking.Fragments;

import android.app.AlertDialog;

import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.CalendarContract;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;


import com.example.barberbooking.Common.Common;
import com.example.barberbooking.Database.CartDataSource;
import com.example.barberbooking.Database.CartDatabase;
import com.example.barberbooking.Database.CartItem;
import com.example.barberbooking.Database.LocalCartDataSource;
import com.example.barberbooking.Model.BookingInformation;
import com.example.barberbooking.Model.EventBus.ConfirmBookingEvent;
import com.example.barberbooking.Model.FCMResponse;
import com.example.barberbooking.Model.FCMsendData;
import com.example.barberbooking.Model.MyNotification;
import com.example.barberbooking.Model.MyToken;
import com.example.barberbooking.R;
import com.example.barberbooking.Retrofit.IFCMApi;
import com.example.barberbooking.Retrofit.RetrofitClient;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.Timestamp;
import com.google.firebase.firestore.CollectionReference;
import com.google.firebase.firestore.DocumentReference;
import com.google.firebase.firestore.DocumentSnapshot;
import com.google.firebase.firestore.FieldValue;
import com.google.firebase.firestore.FirebaseFirestore;
import com.google.firebase.firestore.QuerySnapshot;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;
import java.util.UUID;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import butterknife.Unbinder;
import dmax.dialog.SpotsDialog;
import io.paperdb.Paper;
import io.reactivex.SingleObserver;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;
import io.reactivex.schedulers.Schedulers;

@SuppressWarnings("ALL")
public class BookingStep4Fragment extends Fragment {

    CartDataSource cartDataSource;

    CompositeDisposable compositeDisposable = new CompositeDisposable();
    SimpleDateFormat simpleDateFormat;

    Unbinder unbinder;

    IFCMApi ifcmApi;

    AlertDialog dialog;

    @BindView(R.id.txt_booking_barber_text)
    TextView txt_booking_barber_text;
    @BindView(R.id.txt_booking_time_text)
    TextView txt_booking_time_text;
    @BindView(R.id.txt_salon_address)
    TextView txt_salon_address;
    @BindView(R.id.txt_salon_open_hours)
    TextView txt_salon_open_hours;
    @BindView(R.id.txt_salon_phone)
    TextView txt_salon_phone;
    @BindView(R.id.txt_salon_website)
    TextView txt_salon_website;
    @BindView(R.id.txt_salon_name)
    TextView txt_salon_name;

    @OnClick(R.id.btn_confirm)
    void confirmBooking() {

        dialog.show();



        //DatabaseUtils.getAllCart(CartDatabase.getInstance(getContext()),
        //this);
        compositeDisposable.add(cartDataSource.getAllItemFromCart(Common.currentUser.getPhoneNumber())
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<List<CartItem>>() {
                    @Override
                    public void accept(List<CartItem> cartItems) throws Exception {


                        String startTime = Common.convertTimeSlotToString(Common.currentTimeSlot);
                        String[] convertTime = startTime.split("-"); 

                        String[] startTimeConvert = convertTime[0].split(":");
                        int startHourInt = Integer.parseInt(startTimeConvert[0].trim()); 
                        int startMinInt = Integer.parseInt(startTimeConvert[1].trim()); // We get 00

                        Calendar bookingDateWithourHouse = Calendar.getInstance();
                        bookingDateWithourHouse.setTimeInMillis(Common.currentDate.getTimeInMillis());
                        bookingDateWithourHouse.set(Calendar.HOUR_OF_DAY, startHourInt);
                        bookingDateWithourHouse.set(Calendar.MINUTE, startMinInt);

                        //Create timestamp object and apply to BookingInformation
                        Timestamp timestamp = new Timestamp(bookingDateWithourHouse.getTime());



                        final BookingInformation bookingInformation = new BookingInformation();

                        bookingInformation.setCityBook(Common.city);
                        bookingInformation.setTimestamp(timestamp);
                        bookingInformation.setDone(false); 
                        bookingInformation.setBarberId(Common.currentBarber.getBarberId());
                        bookingInformation.setBarberName(Common.currentBarber.getName());
                        bookingInformation.setCustomerName(Common.currentUser.getName());
                        bookingInformation.setCustomerPhone(Common.currentUser.getPhoneNumber());
                        bookingInformation.setSalonId(Common.currentSalon.getSalonId());
                        bookingInformation.setSalonAddress(Common.currentSalon.getAddress());
                        bookingInformation.setSalonName(Common.currentSalon.getName());
                        bookingInformation.setTime(new StringBuilder(Common.convertTimeSlotToString(Common.currentTimeSlot))
                                .append(" at ")
                                .append(simpleDateFormat.format(bookingDateWithourHouse.getTime())).toString());
                        bookingInformation.setSlot(Long.valueOf(Common.currentTimeSlot));
                        bookingInformation.setCartItemList(cartItems); 


                        DocumentReference bookingDate = FirebaseFirestore.getInstance()
                                .collection("AllSalon")
                                .document(Common.city)
                                .collection("Branch")
                                .document(Common.currentSalon.getSalonId())
                                .collection("Barber")
                                .document(Common.currentBarber.getBarberId())
                                .collection(Common.simpleDateFormat.format(Common.currentDate.getTime()))
                                .document(String.valueOf(Common.currentTimeSlot));


                        bookingDate.set(bookingInformation)
                                .addOnSuccessListener((aVoid) -> {

                                    resetStaticData();
                                    getActivity().finish(); activity
                                    Toast.makeText(getContext(), "Success", Toast.LENGTH_SHORT).show();

                                    //DatabaseUtils.clearCart(CartDatabase.getInstance(getContext()));
                                    cartDataSource.clearCart(Common.currentUser.getPhoneNumber())
                                            .subscribeOn(Schedulers.io())
                                            .observeOn(AndroidSchedulers.mainThread())
                                            .subscribe(new SingleObserver<Integer>() {
                                                @Override
                                                public void onSubscribe(Disposable d) {

                                                }

                                                @Override
                                                public void onSuccess(Integer integer) {
                                                    addToUserBooking(bookingInformation);
                                                }

                                                @Override
                                                public void onError(Throwable e) {
                                                    Toast.makeText(getContext(), "" + e.getMessage(), Toast.LENGTH_SHORT).show();
                                                }
                                            });


                                }).addOnFailureListener(e -> {
                            Toast.makeText(getContext(), "" + e.getMessage(), Toast.LENGTH_SHORT).show();
                        });
                    }
                }, new Consumer<Throwable>() {
                    @Override
                    public void accept(Throwable throwable) throws Exception {
                        Toast.makeText(getContext(), "" + throwable.getMessage(), Toast.LENGTH_SHORT).show();
                    }
                }));

    }

    private void addToUserBooking(BookingInformation bookingInformation) {



        final CollectionReference userBooking = FirebaseFirestore.getInstance()
                .collection("User")
                .document(Common.currentUser.getPhoneNumber())
                .collection("Booking");


        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, 0);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        Timestamp toDayTimeStamp = new Timestamp(calendar.getTime());

        userBooking
                .whereGreaterThanOrEqualTo("timestamp", toDayTimeStamp)
                .whereEqualTo("done", false)
                .limit(1) 
                .get()
                .addOnCompleteListener(task -> {
                    if (task.getResult().isEmpty()) {

                        userBooking.document()
                                .set(bookingInformation)
                                .addOnSuccessListener(aVoid -> {


                                    MyNotification myNotification = new MyNotification();
                                    myNotification.setUid(UUID.randomUUID().toString());
                                    myNotification.setTitle("New Booking");
                                    myNotification.setContent("You have a new appoiment for customer hair care with " + Common.currentUser.getName());
                                    myNotification.setRead(false); // We will only filter notification with 'read' is false on barber staff app
                                    myNotification.setServerTimestamp(FieldValue.serverTimestamp());


                                    FirebaseFirestore.getInstance()
                                            .collection("AllSalon")
                                            .document(Common.city)
                                            .collection("Branch")
                                            .document(Common.currentSalon.getSalonId())
                                            .collection("Barber")
                                            .document(Common.currentBarber.getBarberId())
                                            .collection("Notifications") 
                                            .document(myNotification.getUid()) 
                                            .set(myNotification)
                                            .addOnSuccessListener(new OnSuccessListener<Void>() {
                                                @Override
                                                public void onSuccess(Void aVoid) {
                                                    dialog.dismiss();

                                                    //First , get Token base on Barber id
                                                    FirebaseFirestore.getInstance()
                                                            .collection("Tokens")
                                                            .whereEqualTo("userPhone", Common.currentBarber.getUsername())
                                                            .limit(1)
                                                            .get()
                                                            .addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
                                                                @Override
                                                                public void onComplete(@NonNull Task<QuerySnapshot> task) {
                                                                    if (task.isSuccessful() && task.getResult().size() > 0) {
                                                                        MyToken myToken = new MyToken();
                                                                        for (DocumentSnapshot tokenSnapShot : task.getResult())
                                                                            myToken = tokenSnapShot.toObject(MyToken.class);


                                                                        FCMsendData sendRequest = new FCMsendData();
                                                                        Map<String, String> dataSend = new HashMap<>();
                                                                        dataSend.put(Common.TITLE_KEY, "New Booking");
                                                                        dataSend.put(Common.CONTENT_KEY, "You have new booking from user "+ Common.currentUser.getName());

                                                                        sendRequest.setTo(myToken.getToken());
                                                                        sendRequest.setData(dataSend);

                                                                        compositeDisposable.add(ifcmApi.sendNotification(sendRequest)
                                                                                .subscribeOn(Schedulers.io())
                                                                                .observeOn(AndroidSchedulers.mainThread())
                                                                                .subscribe(new Consumer<FCMResponse>() {
                                                                                    @Override
                                                                                    public void accept(FCMResponse fcmResponse) throws Exception {

                                                                                        dialog.dismiss();

                                                                                        addToCalendar(Common.currentDate,
                                                                                                Common.convertTimeSlotToString(Common.currentTimeSlot));
                                                                                        resetStaticData();
                                                                                        getActivity().finish(); //Close Activity
                                                                                        Toast.makeText(getContext(), "Success", Toast.LENGTH_SHORT).show();

                                                                                    }
                                                                                }, new Consumer<Throwable>() {
                                                                                    @Override
                                                                                    public void accept(Throwable throwable) throws Exception {
                                                                                        Log.d("NOTIFICATION_ERROR", throwable.getMessage());
                                                                                        addToCalendar(Common.currentDate,
                                                                                                Common.convertTimeSlotToString(Common.currentTimeSlot));
                                                                                        resetStaticData();
                                                                                        getActivity().finish(); //Close Activity
                                                                                        Toast.makeText(getContext(), "Success", Toast.LENGTH_SHORT).show();
                                                                                    }
                                                                                }));

                                                                    }
                                                                }
                                                            });
                                                }
                                            });


                                })
                                .addOnFailureListener(new OnFailureListener() {
                                    @Override
                                    public void onFailure(@NonNull Exception e) {
                                        if (dialog.isShowing())
                                            dialog.dismiss();
                                        Toast.makeText(getContext(), e.getMessage(), Toast.LENGTH_SHORT).show();
                                    }
                                });
                    } else {
                        if (dialog.isShowing())
                            dialog.dismiss();

                        resetStaticData();
                        getActivity().finish(); // Close activity
                        Toast.makeText(getContext(), "Success", Toast.LENGTH_SHORT).show();
                    }
                });
    }

    private void addToCalendar(Calendar bookingDate, String startDate) {
        String startTime = Common.convertTimeSlotToString(Common.currentTimeSlot);
        String[] convertTime = startTime.split("-"); //Split ex : 9:00-10:00
        //Get start time : get 9:00
        String[] startTimeConvert = convertTime[0].split(":");
        int startHourInt = Integer.parseInt(startTimeConvert[0].trim());            int startMinInt = Integer.parseInt(startTimeConvert[1].trim());

        String[] endTimeConvert = convertTime[1].split(":");
        int endHourInt = Integer.parseInt(endTimeConvert[0].trim()); 
        int endMinInt = Integer.parseInt(endTimeConvert[1].trim()); 

        Calendar startEvent = Calendar.getInstance();
        startEvent.setTimeInMillis(bookingDate.getTimeInMillis());
        startEvent.set(Calendar.HOUR_OF_DAY, startHourInt); 
        startEvent.set(Calendar.MINUTE, startMinInt); 

        Calendar endEvent = Calendar.getInstance();
        endEvent.setTimeInMillis(bookingDate.getTimeInMillis());
        endEvent.set(Calendar.HOUR_OF_DAY, endHourInt); hour
        endEvent.set(Calendar.MINUTE, endMinInt); 


        SimpleDateFormat calendarDateFormat = new SimpleDateFormat("dd-MM-yyyy HH:mm");

        String startEventTime = calendarDateFormat.format(startEvent.getTime());
        String endEventTime = calendarDateFormat.format(endEvent.getTime());

        addToDeviceCalendar(startEventTime, endEventTime, "Haircut Booking",
                new StringBuilder("Haircut from ")
                        .append(startTime)
                        .append(" with ")
                        .append(Common.currentBarber.getName())
                        .append(" at ")
                        .append(Common.currentSalon.getName()).toString(),
                new StringBuilder("Address: ").append(Common.currentSalon.getAddress()).toString());
    }

    private void addToDeviceCalendar(String startEventTime, String endEventTime, String title, String description, String location) {
        SimpleDateFormat calendarDateFormat = new SimpleDateFormat("dd-MM-yyyy HH:mm");

        try {
            Date start = calendarDateFormat.parse(startEventTime);
            Date end = calendarDateFormat.parse(endEventTime);

            ContentValues event = new ContentValues();



            event.put(CalendarContract.Events.CALENDAR_ID, getCalendar(getContext()));
            event.put(CalendarContract.Events.TITLE, title);
            event.put(CalendarContract.Events.DESCRIPTION, description);
            event.put(CalendarContract.Events.EVENT_LOCATION, location);


            event.put(CalendarContract.Events.DTSTART, start.getTime());
            event.put(CalendarContract.Events.DTEND, end.getTime());
            event.put(CalendarContract.Events.ALL_DAY, 0);
            event.put(CalendarContract.Events.HAS_ALARM, 1);

            String timeZone = TimeZone.getDefault().getID();
            event.put(CalendarContract.Events.EVENT_TIMEZONE, timeZone);

            Uri calendars;
            if (Build.VERSION.SDK_INT >= 22)
                calendars = Uri.parse("content://com.android.calendar/events");
            else
                calendars = Uri.parse("content://calendar/events");
            Uri uri_save = getActivity().getContentResolver().insert(calendars, event);

            Paper.init(getActivity());
            Paper.book().write(Common.EVENT_URI_CACHE, uri_save.toString());


        } catch (ParseException e) {
            e.printStackTrace();
        }


    }

    private String getCalendar(Context context) {

        String gmailIdCalendar = "";
        String projection[] = {"_id", "calendar_displayName"};
        Uri calendars = Uri.parse("content://com.android.calendar/calendars");

        ContentResolver contentResolver = context.getContentResolver();

        Cursor managedCursor = contentResolver.query(calendars, projection, null, null, null);
        if (managedCursor.moveToFirst()) {
            String calName;
            int nameCol = managedCursor.getColumnIndex(projection[1]);
            int idCol = managedCursor.getColumnIndex(projection[0]);
            do {
                calName = managedCursor.getString(nameCol);
                if (calName.contains("@gmail.com")) {
                    gmailIdCalendar = managedCursor.getString(idCol);
                    break; // Exit as soon as have io
                }
            } while (managedCursor.moveToNext());
            managedCursor.close();
        }


        return gmailIdCalendar;
    }

    private void resetStaticData() {
        Common.step = 0;
        Common.currentTimeSlot = -1;
        Common.currentSalon = null;
        Common.currentBarber = null;
        Common.currentDate.add(Calendar.DATE, 0);//Current date
    }



    @Override
    public void onStart() {
        super.onStart();
        EventBus.getDefault().register(this);
    }

    @Override
    public void onStop() {
        EventBus.getDefault().unregister(this);
        super.onStop();
    }


    @Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
    public void setDataBooking(ConfirmBookingEvent event) {
        if (event.isConfirm()) {
            setData();
        }
    }



    private void setData() {
        txt_booking_barber_text.setText(Common.currentBarber.getName());
        txt_booking_time_text.setText(new StringBuilder(Common.convertTimeSlotToString(Common.currentTimeSlot))
                .append(" at ")
                .append(simpleDateFormat.format(Common.currentDate.getTime())));

        txt_salon_address.setText(Common.currentSalon.getAddress());
        txt_salon_website.setText(Common.currentSalon.getWebsite());
        txt_salon_name.setText(Common.currentSalon.getName());
        txt_salon_open_hours.setText(Common.currentSalon.getOpenHours());
    }


    static BookingStep4Fragment instance;
    public static BookingStep4Fragment getInstance() {
        if(instance == null) ;
            instance = new BookingStep4Fragment();
        return instance;
    }


    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        ifcmApi = RetrofitClient.getInstance().create(IFCMApi.class);

        //Apply format for date display on Confirm
        simpleDateFormat = new SimpleDateFormat("dd/MM/yyyy");


        dialog = new SpotsDialog.Builder().setContext(getContext()).setCancelable(false)
                .build();
    }

    @Override
    public void onDestroy() {
        compositeDisposable.clear();
        super.onDestroy();
        { if (dialog != null) { dialog.dismiss(); dialog = null; }}
    }



    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        super.onCreateView(inflater, container, savedInstanceState);

        View itemView = inflater.inflate(R.layout.fragment_bookingstep_four, container, false);
        unbinder = ButterKnife.bind(this, itemView);

        //Remember init cartDataSource here (onCreateView) , if you don't want to get null reference
        //Because getContext() return null
        cartDataSource = new LocalCartDataSource(CartDatabase.getInstance(getContext()).cartDAO());

        return itemView;

    }


}

2 Answers2

0

Your Text view not initialized before call it.

ashok
  • 444
  • 4
  • 8
0

Check your textView id or initialization of textView.

Avinash
  • 744
  • 3
  • 10