0

This is the login screen, which leads to the next screen(Chat Screen)

This is the Chat Screen- which I am unable to navigate to

I am trying to implement a chat feature wherein both the login and the chat screens are fragments.I am not any getting errors. But, the app is not navigating to the chat screen. I don't know where I am missing. Any kind of suggestions would be appreciated.

******** Login Fragment********

public class LoginFragment extends Fragment {

private EditText mUsernameView;
private Button signInButton;
private String mUsername;
private Socket mSocket;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {

    View loginview = inflater.inflate(R.layout.fragment_login, container, false);

    ChatApplication app = (ChatApplication) getActivity().getApplication();
    mSocket = app.getSocket();

    // this is the login form
    mUsernameView = (EditText) loginview.findViewById(R.id.username_input);
    mUsernameView.setOnEditorActionListener(new TextView.OnEditorActionListener()
    {
        @Override
        public boolean onEditorAction(TextView textView, int id, KeyEvent keyEvent)
        {
            if(id == R.id.login || id == EditorInfo.IME_NULL)
            {
                attemptLogin();
                return true;
            }
                return false;
        }
    });

    signInButton = (Button) loginview.findViewById(R.id.sign_in_button);
    signInButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v)
        {
            attemptLogin();
        }
    });

    mSocket.on("login",onLogin);

    return loginview;
}

@Override
public void onDestroy() {
    super.onDestroy();

    mSocket.off("login", onLogin);
}

/*
    This method attempts the following
    1- clears the error message/resets the error message.
    2- checks if the user has entered valid username
    3- attempts user login
 */
private void attemptLogin()
{
    mUsernameView.setError(null);  //1
    String username = mUsernameView.getText().toString().trim();
    if(TextUtils.isEmpty(username))  //2
    {
        mUsernameView.setError("This field is required!");
        mUsernameView.requestFocus();
        return;
    }

    mUsername = username;

    mSocket.emit("add user", username); //3
}

private Emitter.Listener onLogin = new Emitter.Listener()
{
    @Override
    public void call(Object... args)
    {
        JSONObject data = (JSONObject) args[0];
        int numUsers;
        try
        {
            numUsers = data.getInt("numUsers");
        }
        catch (JSONException e)
        {
            return;
        }

        Intent intent = new Intent();
        intent.putExtra("username",mUsername);
        intent.putExtra("numUsers",numUsers);
        getActivity().setResult(RESULT_OK,intent);
        getActivity().finish();
    }
};

}

************** Chat Fragment *************

   public class ChatFragment extends Fragment
{


    private static final int REQUEST_LOGIN = 1;

    private static final int TYPING_TIMER_LENGTH = 600;

    private RecyclerView mMessagesView;
    private EditText mInputMessageView;
    private List<Message> mMessages = new ArrayList<Message>();
    private RecyclerView.Adapter mAdapter;
    private boolean mTyping = false;
    private Handler mTypingHandler = new Handler();
    private String mUsername;
    private Socket mSocket;

    private Boolean isConnected = true;

    public ChatFragment() {
        super();
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        mAdapter = new MessageAdapter(context, mMessages);
    }

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

        setHasOptionsMenu(true);

        ChatApplication app = (ChatApplication) getActivity().getApplication();
        mSocket = app.getSocket();
        mSocket.on(Socket.EVENT_CONNECT,onConnect);
        mSocket.on(Socket.EVENT_DISCONNECT,onDisconnect);
        mSocket.on(Socket.EVENT_CONNECT_ERROR, onConnectError);
        mSocket.on(Socket.EVENT_CONNECT_TIMEOUT, onConnectError);
        mSocket.on("new message", onNewMessage);
        mSocket.on("user joined", onUserJoined);
        mSocket.on("user left", onUserLeft);
        mSocket.on("typing", onTyping);
        mSocket.on("stop typing", onStopTyping);
        mSocket.connect();

        startSignIn();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_chat, container, false);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();

        mSocket.disconnect();

        mSocket.off(Socket.EVENT_CONNECT, onConnect);
        mSocket.off(Socket.EVENT_DISCONNECT, onDisconnect);
        mSocket.off(Socket.EVENT_CONNECT_ERROR, onConnectError);
        mSocket.off(Socket.EVENT_CONNECT_TIMEOUT, onConnectError);
        mSocket.off("new message", onNewMessage);
        mSocket.off("user joined", onUserJoined);
        mSocket.off("user left", onUserLeft);
        mSocket.off("typing", onTyping);
        mSocket.off("stop typing", onStopTyping);
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        mMessagesView = (RecyclerView) view.findViewById(R.id.messages);
        mMessagesView.setLayoutManager(new LinearLayoutManager(getActivity()));
        mMessagesView.setAdapter(mAdapter);

        mInputMessageView = (EditText) view.findViewById(R.id.message_input);
        mInputMessageView.setOnEditorActionListener(new TextView.OnEditorActionListener() {
            @Override
            public boolean onEditorAction(TextView v, int id, KeyEvent event) {
                if (id == R.id.send || id == EditorInfo.IME_NULL) {
                    attemptSend();
                    return true;
                }
                return false;
            }
        });
        mInputMessageView.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                if (null == mUsername) return;
                if (!mSocket.connected()) return;

                if (!mTyping) {
                    mTyping = true;
                    mSocket.emit("typing");
                }

                mTypingHandler.removeCallbacks(onTypingTimeout);
                mTypingHandler.postDelayed(onTypingTimeout, TYPING_TIMER_LENGTH);
            }

            @Override
            public void afterTextChanged(Editable s) {
            }
        });

        ImageButton sendButton = (ImageButton) view.findViewById(R.id.send_button);
        sendButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                attemptSend();
            }
        });
    }

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

        mUsername = data.getStringExtra("username");
        int numUsers = data.getIntExtra("numUsers", 1);

        addLog(getResources().getString(R.string.message_welcome));
        addParticipantsLog(numUsers);
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        // Inflate the menu; this adds items to the action bar if it is present.
        inflater.inflate(R.menu.menu_main, menu);
    }

    @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();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_leave) {
            leave();
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    private void addLog(String message) {
        mMessages.add(new Message.Builder(Message.TYPE_LOG)
                .message(message).build());
        mAdapter.notifyItemInserted(mMessages.size() - 1);
        scrollToBottom();
    }

    private void addParticipantsLog(int numUsers) {
        addLog(getResources().getQuantityString(R.plurals.message_participants, numUsers, numUsers));
    }

    private void addMessage(String username, String message) {
        mMessages.add(new Message.Builder(Message.TYPE_MESSAGE)
                .username(username).message(message).build());
        mAdapter.notifyItemInserted(mMessages.size() - 1);
        scrollToBottom();
    }

    private void addTyping(String username) {
        mMessages.add(new Message.Builder(Message.TYPE_ACTION)
                .username(username).build());
        mAdapter.notifyItemInserted(mMessages.size() - 1);
        scrollToBottom();
    }

    private void removeTyping(String username) {
        for (int i = mMessages.size() - 1; i >= 0; i--) {
            Message message = mMessages.get(i);
            if (message.getType() == Message.TYPE_ACTION && message.getUsername().equals(username)) {
                mMessages.remove(i);
                mAdapter.notifyItemRemoved(i);
            }
        }
    }

    private void attemptSend() {
        if (null == mUsername) return;
        if (!mSocket.connected()) return;

        mTyping = false;

        String message = mInputMessageView.getText().toString().trim();
        if (TextUtils.isEmpty(message)) {
            mInputMessageView.requestFocus();
            return;
        }

        mInputMessageView.setText("");
        addMessage(mUsername, message);

        // perform the sending message attempt.
        mSocket.emit("new message", message);
    }

    private void startSignIn() {
        mUsername = null;
    /* Error:
        Intent intent = new Intent(getActivity(), LoginFragment.class);
        startActivityForResult(intent, REQUEST_LOGIN);
    */

     // Solution 1: for calling a fragment from a fragment
        Intent intent = new Intent(getActivity(),LoginFragment.class);
        getActivity().startActivityForResult(intent,REQUEST_LOGIN);

/*
     // Solution 2: for calling a fragment from a fragment
        LoginFragment loginFragment = new LoginFragment();
        FragmentManager fManager = getFragmentManager();
        FragmentTransaction fTransaction = fManager.beginTransaction();
        fTransaction.replace(R.id.id_fragment_chat,loginFragment);
        fTransaction.addToBackStack(null);
        fTransaction.commit();

*/
    }

    private void leave() {
        mUsername = null;
        mSocket.disconnect();
        mSocket.connect();
        startSignIn();
    }

    private void scrollToBottom() {
        mMessagesView.scrollToPosition(mAdapter.getItemCount() - 1);
    }

    private Emitter.Listener onConnect = new Emitter.Listener() {
        @Override
        public void call(Object... args) {
            getActivity().runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    if(!isConnected) {
                        if(null!=mUsername)
                            mSocket.emit("add user", mUsername);
                        Toast.makeText(getActivity().getApplicationContext(),
                                R.string.connect, Toast.LENGTH_LONG).show();
                        isConnected = true;
                    }
                }
            });
        }
    };
.
.
.
}
Foshiba
  • 225
  • 3
  • 9
  • There should be errors... `LoginFragment` is not an Activity. You can't use `startActivity` with it – OneCricketeer Dec 26 '16 at 22:14
  • Unclear how you are trying to start `ChatFragment`, though – OneCricketeer Dec 26 '16 at 22:17
  • Yes, LoginFragment is not an activity.. – Foshiba Dec 26 '16 at 22:29
  • I followed the following ways for call a fragment from another fragment. // Solution 1: for calling a fragment from a fragment Intent intent = new Intent(getActivity(),LoginFragment.class); getActivity().startActivityForResult(intent,REQUEST_LOGIN); – Foshiba Dec 26 '16 at 22:36
  • // Solution 2: for calling a fragment from a fragment LoginFragment loginFragment = new LoginFragment(); FragmentManager fManager = getFragmentManager(); FragmentTransaction fTransaction = fManager.beginTransaction(); fTransaction.replace(R.id.id_fragment_chat,loginFragment); fTransaction.addToBackStack(null); fTransaction.commit(); – Foshiba Dec 26 '16 at 22:36
  • 1
    Where is your activity code ? Please add it – Ibrahim Disouki Dec 26 '16 at 22:37
  • Both the above ways din't work – Foshiba Dec 26 '16 at 22:39
  • I am implementing this in a Navigation Drawer. This is the activity. – Foshiba Dec 26 '16 at 22:40
  • Solution 1 is not a solution for starting a Fragment. Solution 2 won't work *inside a Fragment*. You shouldn't be starting Fragments within Fragments anyways, ideally. – OneCricketeer Dec 27 '16 at 00:37
  • For example, read this post. Make the callback replace the Fragment *within the Activity*. http://stackoverflow.com/questions/24777985/how-to-implement-onfragmentinteractionlistener – OneCricketeer Dec 27 '16 at 00:37
  • thanks for the reference.. – Foshiba Dec 27 '16 at 10:54
  • But, I am still confused :( .. I think the code is breaking at this method.. private void startSignIn() { mUsername = null; Intent intent = new Intent(getActivity(), LoginFragment.class); startActivityForResult(intent, 0); } ------ Here, LoginFragment is a fragment. This gave me error so I used the workaround by using getActivity() for startActivityForResult as mentioned in the previous comment (//Solution 1) – Foshiba Dec 27 '16 at 11:00

2 Answers2

2

Use core fragment structure instead of using direct extends

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;

/**
 *
 * This is main core fragment. All fragment defined in this project that extends this fragment.
 *
 * @author viral
 *
 */
public class CoreFragment extends Fragment {

    private static FragmentManager fm;
    private CharSequence tabTitle;

    /**
     * This method switch fragment.
     * 
     * @param fragment - from fragment 
     * @param viewReplace - Destination view/container
     * 
     */
    public void switchFragment(Fragment fragment, int viewReplace){
        try {
            FragmentManager fragmentManager = getFragmentManager();
            if(fragmentManager != null)
                fm = fragmentManager;

            fm.beginTransaction()
                .replace(viewReplace, fragment)
                .commit();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * This method switch fragment.
     * 
     * @param fragment - from fragment 
     * @param viewReplace - Destination view/container
     * 
     */
    public void switchFragmentWithBackstack(Fragment fragment, int viewReplace){
        try {
            FragmentManager fragmentManager = getFragmentManager();
            if(fragmentManager != null)
                fm = fragmentManager;
            fm.beginTransaction()
                .replace(viewReplace, fragment)
                .addToBackStack(null)
                .commit();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Then use switchFragment/switchFragmentWithBackstack method as per your application require.

Your all fragment extends CoreFragment

0

About your private void startSignIn() { mUsername = null; Intent intent = new Intent(getActivity(), LoginFragment.class); startActivityForResult(intent, 0); }... What do you want to do? Start another Activity? Then you should call this activity, and in this activity to add this fragment. Or, if you want to replace one fragment by another in the same activity, you should do it like so, instead startActivity:

YourFragment fragment = new YourFragment();
        FragmentManager fragmentManager = getSupportFragmentManager();
        fragmentManager.beginTransaction()
                .replace(R.id.fragmentContainer, fragment, YOUR_TAG)
                .commit();
Hetfieldan24
  • 198
  • 11