socketio / socket.io-client-java

Full-featured Socket.IO Client Library for Java, which is compatible with Socket.IO v1.0 and later.
https://socketio.github.io/socket.io-client-java/installation.html
Other
5.34k stars 975 forks source link

TextView.setText() giving an error about thread in socket.io java client #580

Open rohankeskar19 opened 5 years ago

rohankeskar19 commented 5 years ago

`package com.example.chatapplication;

import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatDelegate; import androidx.core.content.ContextCompat;

import android.content.Intent; import android.content.SharedPreferences; import android.os.Bundle; import android.os.Handler; import android.os.StrictMode; import android.text.Editable; import android.text.TextWatcher; import android.util.Base64; import android.util.Log; import android.view.View; import android.widget.EditText; import android.widget.ImageView; import android.widget.TextView;

import com.bumptech.glide.Glide; import com.example.chatapplication.Models.Freind; import com.example.chatapplication.Models.User; import com.github.nkzawa.emitter.Emitter; import com.github.nkzawa.socketio.client.IO; import com.github.nkzawa.socketio.client.Socket; import com.vanniktech.emoji.EmojiManager; import com.vanniktech.emoji.EmojiPopup; import com.vanniktech.emoji.EmojiProvider; import com.vanniktech.emoji.ios.IosEmojiProvider;

import org.json.JSONObject;

import java.io.UnsupportedEncodingException; import java.util.Timer; import java.util.TimerTask;

import static android.app.UiModeManager.MODE_NIGHT_AUTO;

public class ChatActivity extends AppCompatActivity {

Freind freind;
String token;

ImageView freindProfileImageView,sendButtonImageView;
TextView freindNameTextView,freindStatusTextView;

EditText editText;

Socket socket;

User user;

boolean isOnline;

private static final String TAG = "ChatActivity";

long delay = 2000;
long lastTextEdit = 0;
Handler handler = new Handler();

private Runnable inputFinishChecker = new Runnable() {
    @Override
    public void run() {
        if (System.currentTimeMillis() > (lastTextEdit + delay - 500)){
            try{
                Log.d(TAG, "Stopped typing call: " + freind.getId());
                final JSONObject jsonObject = new JSONObject();
                jsonObject.put("toId",freind.getId());
                socket.emit("stop-typing",jsonObject);
            }
            catch (Exception e){
                e.printStackTrace();
            }
        }
    }
};

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

    String url = getString(R.string.protocol) + "://" + getString(R.string.host) + ":" + getString(R.string.SOCKET_PORT);
    try {
        socket = IO.socket(url);

        editText = findViewById(R.id.messageEditText);
        freindProfileImageView = findViewById(R.id.freindProfileImageView);
        freindNameTextView = findViewById(R.id.freindNameTextView);
        freindStatusTextView = findViewById(R.id.freindStatusTextView);
        sendButtonImageView = findViewById(R.id.sendButton);

        Intent intent = getIntent();

        if (intent.hasExtra("freind")){
            freind = (Freind) intent.getSerializableExtra("freind");
        }

        SharedPreferences sharedPreferences = getApplicationContext().getSharedPreferences("authData",0);

        token = sharedPreferences.getString("token","null");

        if (token.equals("null")){
            finish();
        }

        String decodedToken = decoded(token);

        JSONObject jsonObject = new JSONObject(decodedToken);
        JSONObject user1 = jsonObject.getJSONObject("user");

        user = new User(user1.getString("id"),user1.getString("name"),user1.getString("email"),user1.getString("username"),user1.getString("profileUrl"),"","");

        int length = user.getProfileUrl().length();

        user.setProfileUrl("https://" + user.getProfileUrl().substring(2,length));

        sendButtonImageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String message = editText.getText().toString().trim();

                if (message.equals("")){

                }
                else{

                }
            }
        });

        init();

        EmojiManager.install(new IosEmojiProvider());
    }
    catch (Exception e){
        e.printStackTrace();
    }

}

private void init(){
    Glide.with(this).load(freind.getProfileUrl()).into(freindProfileImageView);
    freindNameTextView.setText(freind.getName());

    try{
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("id",freind.getId());
        socket.emit("isOnline",jsonObject);

        socket.on("online", new Emitter.Listener() {
            @Override
            public void call(Object... args) {
                try {
                    JSONObject jsonObject = (JSONObject) args[0];
                    Log.d(TAG, "call: " + jsonObject);
                    JSONObject userObject = jsonObject.getJSONObject("user");
                    String id = userObject.getString("id");

                    if (id.equals(freind.getId())){
                        freindStatusTextView.setText("Online");
                        freindStatusTextView.setTextColor(ContextCompat.getColor(ChatActivity.this,R.color.gray));
                    }
                }
                catch (Exception e){
                    e.printStackTrace();
                }
            }
        });

        socket.on("isOnline", new Emitter.Listener() {
            @Override
            public void call(Object... args) {
                try{
                    JSONObject jsonObject = (JSONObject) args[0];

                    String id = jsonObject.getString("id");
                    if (id.equals(freind.getId())){
                        freindStatusTextView.setText("Online");
                        freindStatusTextView.setTextColor(ContextCompat.getColor(ChatActivity.this,R.color.gray));
                        isOnline = true;
                    }

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

        socket.on("isOffline", new Emitter.Listener() {
            @Override
            public void call(Object... args) {
                try{
                    JSONObject jsonObject = (JSONObject) args[0];

                    String id = jsonObject.getString("id");
                    if (id.equals(freind.getId())){
                        freindStatusTextView.setText("Offline");
                        freindStatusTextView.setTextColor(ContextCompat.getColor(ChatActivity.this,R.color.gray));
                        isOnline = false;
                    }

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

        socket.on("offline", new Emitter.Listener() {
            @Override
            public void call(Object... args) {
                try {
                    JSONObject jsonObject = (JSONObject) args[0];

                    String id = jsonObject.getString("id");
                    if (id.equals(freind.getId())){
                        freindStatusTextView.setText("Offline");
                        freindStatusTextView.setTextColor(ContextCompat.getColor(ChatActivity.this,R.color.gray));
                        isOnline = false;
                    }
                }
                catch (Exception e){
                    e.printStackTrace();
                }
            }
        });

        editText.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) {

            }

            @Override
            public void afterTextChanged(Editable s) {
                try {
                    if (s.length() > 0){
                        Log.d(TAG, "call: " + freind.getId());
                        final JSONObject jsonObject = new JSONObject();
                        jsonObject.put("toId",freind.getId());
                        socket.emit("typing",jsonObject);
                        lastTextEdit = System.currentTimeMillis();
                        handler.postDelayed(inputFinishChecker,delay);
                    }

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

            }
        });

        socket.on("typing", new Emitter.Listener() {
            @Override
            public void call(Object... args) {
                try{
                    Log.d(TAG, "call: " + freind.getId());

                    JSONObject jsonObject = (JSONObject) args[0];
                    String id = jsonObject.getString("id");
                    Log.d(TAG, "call: Typing " +  id);
                    if (id.equals(freind.getId())){
                        freindStatusTextView.setText("typing...");
                        freindStatusTextView.setTextColor(ContextCompat.getColor(ChatActivity.this,R.color.green));
                    }

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

        socket.on("stop-typing", new Emitter.Listener() {
            @Override
            public void call(Object... args) {
                try{
                    Log.d(TAG, "Stop call: " + freind.getId());

                    JSONObject jsonObject = (JSONObject) args[0];
                    String id = jsonObject.getString("id");
                    Log.d(TAG, "call: Stop Typing " +  id);
                    if (id.equals(freind.getId())){

                        if (isOnline){
                            freindStatusTextView.setText("Online");
                            freindStatusTextView.setTextColor(ContextCompat.getColor(ChatActivity.this,R.color.gray));
                        }
                        else{
                            freindStatusTextView.setText("Online");
                            freindStatusTextView.setTextColor(ContextCompat.getColor(ChatActivity.this,R.color.gray));
                        }
                    }

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

}

private static String[] split;

public static String decoded(String JWTEncoded) throws Exception {
    try {
        split = JWTEncoded.split("\\.");

    } catch (Exception e) {
        //Error
    }
    return getJson(split[1]);
}

private static String getJson(String strEncoded) throws UnsupportedEncodingException {
    byte[] decodedBytes = Base64.decode(strEncoded, Base64.URL_SAFE);
    return new String(decodedBytes, "UTF-8");
}

}

`

When i try to change the text based on events like typing or stopped typing, or wentOffline or came online

This is giving me an error like

android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

mmmatey commented 5 years ago

@rohankeskar19 Whole point working with sockets.io client in java is that library returns data in own thread, meaning not on main/ui thread. So if you want to update your views, you should send your data to UI thread. Simply you can do it with textview.post(()- > { textView.setText(dataFromSocket); });