Android Java_WebSocket实现与后台聊天通讯

转载请带上原著连接哦~~ 

http://blog.csdn.net/lhk147852369/article/details/78616341

弄了2天做出来的聊天,真的是心痛,也没什么难得东西,主要还是不熟悉,就会出错,很尴尬!

先放松一下:来段舞蹈吧!

 

WebSocket简介

WebSocket协议是基于TCP的一种新的网络协议。它实现了浏览器与服务器全双工(full-duplex)通信——允许服务器主动发送信息给客户端。

WebSocket通信协议于2011年被IETF定为标准RFC 6455,并被RFC7936所补充规范。

 

 

话不多说,先上图:

不过图片的话也没有多少张,简单聊天而已嘛

对了,代码写的有点粗糙,咱就这水平,不喜勿喷啊

这次尽量发全点大家可以直接使用,是我所希望的

这是采用recycleview绘制的聊天界面:

 

 

 

我们发送文字传递到后台,后台会收到我们穿的json去进行解析,进行记录

 

 

好了图片也就这样了,没什么毛病,后续我们可以自行添加动态效果。

 

 

ok进入正题,走着您呢~

主界面如下:

两张.9图 放在mipmap的xhdpi中,虽然会报红,但是没关系,继续用就可以了

在Drawable图片会被放大的

 

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#F7F6F6"
    tools:context="com.lgoutech.chatuidesigndemo.MainActivity">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="44dp"
        android:gravity="center_vertical"
        android:background="#00A9FF"
        android:layout_alignParentTop="true"
        android:id="@+id/tab_top"
        >
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="客户"
            android:textSize="18sp"
            android:layout_centerInParent="true"
            android:textColor="#FFF"
            />
    </RelativeLayout>

    <android.support.v7.widget.RecyclerView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/chat_recy"
        android:layout_below="@+id/tab_top"
        android:layout_above="@+id/chat_lay"
        >

    </android.support.v7.widget.RecyclerView>


    <View
        android:layout_width="match_parent"
        android:layout_height="1px"
        android:background="#B2B2B2"
        android:layout_above="@+id/chat_lay"
        />
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:orientation="horizontal"
        android:layout_alignParentBottom="true"
        android:background="#F9F9F9"
        android:gravity="center_vertical"
        android:padding="3dp"
        android:id="@+id/chat_lay"
        >
        <ImageView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:src="@mipmap/icon_chat_add"
            android:layout_weight="1"
            android:id="@+id/img_add"
            />
        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="8"
            android:background="@drawable/chat_edit_bg"
            android:layout_margin="6dp"
            android:gravity="center"
            >
            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="@null"
                android:padding="3dp"
                android:textSize="14sp"
                android:id="@+id/edit_context"
                android:maxLines="3"
                />
        </LinearLayout>

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:text="发送"
            android:layout_weight="1.5"
            android:textSize="18sp"
            android:gravity="center"
            android:id="@+id/txt_send"
            android:textColor="@color/text_send_press"
            />
    </LinearLayout>

</RelativeLayout>

 

 

 

记得添加网络权限哦!!!

 

所需要用的第三方框架

 

 compile 'com.android.support:recyclerview-v7:26.1.0'
    compile "org.java-websocket:Java-WebSocket:1.3.6"
    compile 'com.squareup.retrofit2:converter-gson:2.1.0'

 

 

 

主界面MainActivity: 已经做了相关的注释

 

public class MainActivity extends AppCompatActivity implements View.OnClickListener, View.OnTouchListener {

    private static final int STATUS_MESSAGE = 0x00;
    private RecyclerView chatRecy;
    private ContextMsg msg;
    private List<ContextMsg> msgList;
    private ChatRecyAdapter chatRecyAdapter;
    private EditText editContext;
    private TextView txtSend;
//大家自己找吧,我用的内网,大家也用不了的,哈哈
    private static final String url = "ws://服务端地址:端口97/";
    private URI uri;
    JWebSClient client;

    private Handler mhandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            String mess = (String) msg.obj;
            switch (msg.what) {
                case STATUS_MESSAGE:
                    setListSent(mess, ContextMsg.TYPE_RECEIVED);
                    break;
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initSocketClient();
        initView();
        initCharRecy();

    }


    @Override
    protected void onDestroy() {
        super.onDestroy();
//activity 销毁时 关闭连接
        closeConnect();
    }

    private void initView() {
        chatRecy = findViewById(R.id.chat_recy);
        editContext = findViewById(R.id.edit_context);
        txtSend = findViewById(R.id.txt_send);

        txtSend.setOnClickListener(this);

        chatRecy.setOnTouchListener(this);


//这里是对发送按钮进行了处理,用户体验吗 ,你们懂得
        editContext.addTextChangedListener(new MyTxtSendWatcher());
    }

    private void initCharRecy() {
        chatRecyAdapter = new ChatRecyAdapter(MainActivity.this, getList());
        chatRecy.setLayoutManager(new LinearLayoutManager(this));
        chatRecy.setAdapter(chatRecyAdapter);
    }
//模拟数据
    private List<ContextMsg> getList() {
        msgList = new ArrayList<>();
        msgList.add(new ContextMsg("你好", ContextMsg.TYPE_RECEIVED));
        msgList.add(new ContextMsg("hello", ContextMsg.TYPE_SENT));
        msgList.add(new ContextMsg("见到你很高兴", ContextMsg.TYPE_RECEIVED));
        msgList.add(new ContextMsg("me to", ContextMsg.TYPE_SENT));
        return msgList;
    }
//这里设置文字显示在recycle
    private void setListSent(String send, int type) {
        if (type == ContextMsg.TYPE_SENT) {
            msgList.add(new ContextMsg(send, ContextMsg.TYPE_SENT));
            editContext.setText("");
        } else {
            msgList.add(new ContextMsg(send, ContextMsg.TYPE_RECEIVED));
        }
        chatRecyAdapter = new ChatRecyAdapter(MainActivity.this, msgList);
        chatRecyAdapter.notifyDataSetChanged();
        chatRecy.scrollToPosition(chatRecyAdapter.getItemCount() - 1);

    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.txt_send:
                String editText = editContext.getText().toString();
                setListSent(editText, ContextMsg.TYPE_SENT);
                sendJsonObject(editText);
                break;

        }
    }


    private void senJsonInit() {
        try {
            JSONObject msg = new JSONObject();
            msg.put("from", 2);

            JSONObject init = new JSONObject();
            init.put("type", "init");
            init.put("msg", msg);

            sendMsg(init.toString());
            Log.e("init", "Init初始化成功");
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    private void sendJsonObject(String context) {
        try {
            JSONObject msg = new JSONObject();
            msg.put("to", 1);
            msg.put("content", context);
            msg.put("from", 2);
            msg.put("headimg", "");

            JSONObject toOne = new JSONObject();
            toOne.put("type", "msg");
            toOne.put("msg", msg);
            sendMsg(toOne.toString());

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

    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        switch (v.getId()) {
            case R.id.chat_recy:
//在我们的recycleview中 触摸到后 会隐藏输入法键盘的
                hideSoftInput(MainActivity.this, v);
                break;

        }
        return false;
    }

//显示输入法
    public static void showSoftInput(Context context, View view) {
        InputMethodManager imm = (InputMethodManager) context.getSystemService(Activity.INPUT_METHOD_SERVICE);
        imm.showSoftInput(view, InputMethodManager.SHOW_FORCED);
    }
//隐藏输入法
    public static void hideSoftInput(Context context, View view) {
        InputMethodManager imm = (InputMethodManager) context.getSystemService(Activity.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(view.getWindowToken(), 0);

    }

//打开socket连接
    private void initSocketClient() {
        uri = URI.create(url);
        client = new JWebSClient(uri) {
            @Override
            public void onMessage(String message) {
                Log.e("onMessage", message);
                ReceivedMsg receivedMsg = GsonManager.getGson(message, ReceivedMsg.class);
                Message msg = new Message();
                msg.what = STATUS_MESSAGE;
                msg.obj = receivedMsg.getMsg().getContent();
                mhandler.sendMessage(msg);
            }

        };
        connect();



    }

    //连接
    private void connect() {
        new Thread() {
            @Override
            public void run() {
                try {
                    client.connectBlocking();
                    Log.e("connectBlocking", "连接成功");

                    if(client.isOpen()){
                        senJsonInit();
                    }

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }.start();

    }

    //断开连接
    private void closeConnect() {
        try {
            if (null != client) {
                client.close();

            }
        } catch (Exception e) {
            e.printStackTrace();
            Log.e("Socket", "断开连接异常");
        } finally {
            client = null;
        }
    }

    //发送消息

    /**
     *
     */
    private void sendMsg(String msg) {
        if (null != client) {
            client.send(msg);
            Log.e("发送的消息", msg);
        }
    }

    private class MyTxtSendWatcher implements 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(TextUtils.isEmpty(editContext.getText())){
                txtSend.setClickable(false);
                txtSend.setTextColor(getResources().getColor(R.color.text_send_press));
            }else {
                txtSend.setClickable(true);
                txtSend.setTextColor(getResources().getColor(R.color.text_send_normal));
            }
        }

        @Override
        public void afterTextChanged(Editable s) {

        }
    }
}

 

接下来使我们的websocket,因为我们使用的是java_websocket所以使用方法如下:

 

 

 

public class JWebSClient extends WebSocketClient {


    public JWebSClient(URI serverUri) {
        super(serverUri,new Draft_6455());
    }

    @Override
    public void onOpen(ServerHandshake handshakedata) {
        Log.e("JWebSClient", "连接打开onOpen");
    }

    @Override
    public void onMessage(String message) {
        Log.e("JWebSClient", message);

    }

    @Override
    public void onClose(int code, String reason, boolean remote) {
        Log.e("JWebSClient", "关闭 断开连接onClose");
    }

    @Override
    public void onError(Exception ex) {
        Log.e("JWebSClient", "错误 onError");
    }

}

很简单。也有了注释的,在mainActivity中使用的

 

 

对于recycleview的anapter:

 

public class ChatRecyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    private List<ContextMsg> mList;
    private Context mContext;
    private LayoutInflater inflater;
    public ChatRecyAdapter(Context context, List<ContextMsg> list) {
        mList = list;
        mContext = context;
        inflater = LayoutInflater.from(context);
    }

    //onCreateViewHolder()用于创建ViewHolder实例
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

        if (viewType == ContextMsg.TYPE_SENT) {
            View view = inflater.inflate(R.layout.item_right_chat, parent, false);
            RightHolder rightHolder = new RightHolder(view);
            return rightHolder;
        }else if (viewType == ContextMsg.TYPE_RECEIVED){
            View view = inflater.inflate(R.layout.item_left_chat,parent,false);
            LeftHolder leftHolder = new LeftHolder(view);
            return leftHolder;
        }

        return null;
    }

    //onBindViewHolder()用于对RecyclerView子项的数据进行赋值,会在每个子项被滚动到屏幕内的时候执行
    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {

        if (holder instanceof RightHolder) {
            RightHolder rightHolder = (RightHolder) holder;
            if (mList != null) {
                rightHolder.tvChatContent.setText(mList.get(position).getContent());
                rightHolder.imgChatHead.setImageResource(R.mipmap.head_img);

            }
        }else if (holder instanceof LeftHolder){
            LeftHolder leftHolder = (LeftHolder) holder;
            if (mList!=null){
                leftHolder.tvChatContent.setText(mList.get(position).getContent());
                leftHolder.imgChatHead.setImageResource(R.mipmap.head_img);
            }
        }

    }

    @Override
    public int getItemCount() {
        if (mList!=null)
            return mList.size();
        else
            return 0;
    }

    @Override
    public int getItemViewType(int position) {
        return mList.get(position).getType();
    }
//左布局
    public class LeftHolder extends RecyclerView.ViewHolder {
        private TextView tvChatContent;
        private ImageView imgChatHead;
        public LeftHolder(View itemView) {
            super(itemView);
            tvChatContent =  itemView.findViewById(R.id.chat_content_text);
            imgChatHead =  itemView.findViewById(R.id.chat_item_header);
        }
    }
//右布局
    public class RightHolder extends RecyclerView.ViewHolder {
        private TextView tvChatContent;
        private  ImageView imgChatHead;
        public RightHolder(View itemView) {
            super(itemView);
            tvChatContent =  itemView.findViewById(R.id.chat_content_text);
            imgChatHead =  itemView.findViewById(R.id.chat_item_header);
        }
    }

}


看到这里有人问了,两个布局,一样为什么要这么写呢?

 

为什么,我哪知道~

写别的方式,holder找不到你的控件,怎么办,有大神可以给一下解决方式吗?谢谢了

 

 

接下来就是从后台传递过来的数据,实体:

 

public class ReceivedMsg {

    private String type;
    private ContextMsg msg;

    public void setType(String type) {
        this.type = type;
    }

    public String getType() {
        return type;
    }

    public void setMsg(ContextMsg msg) {
        this.msg = msg;
    }

    public ContextMsg getMsg() {
        return msg;
    }


    public class Msg {

        private int to;
        private String content;
        private int from;
        private String headimg;
        public void setTo(int to) {
            this.to = to;
        }
        public int getTo() {
            return to;
        }

        public void setContent(String content) {
            this.content = content;
        }
        public String getContent() {
            return content;
        }

        public void setFrom(int from) {
            this.from = from;
        }
        public int getFrom() {
            return from;
        }

        public void setHeadimg(String headimg) {
            this.headimg = headimg;
        }
        public String getHeadimg() {
            return headimg;
        }

    }
}

 

 

 

Gson工具解析json数据,已封装,使用方法就在代码中

 

 

public class GsonManager<T>{

    public static <T>T  getGson(String json,Class<T> tClass){
        Gson gson=new Gson();
        return gson.fromJson(json,tClass);
    }

    public static <T> String mapToJson(Map<String, T> map) {
        Gson gson = new Gson();
        String jsonStr = gson.toJson(map);
        return jsonStr;
    }
}

 

 

大家根据自己需要,适当修改即可!
注意:

 
 client.connectBlocking();
                    Log.e("connectBlocking", "连接成功");

                    if(client.isOpen()){
                        senJsonInit();
                    }

 

跟大家提一下,这里用到了connectBlocking 而没有用connect为什么呢?

 

1.因为后台的原因,我是需要在连接成功后传递一下我是哪位用户的,所以在连接成功后我会想后台发送一个json

2.所以这里Blocking 会多出一个等待操作,然后我判断了连接打没打开,进行发送数据,否则会报错的哦,

3.错误原因在于未连接就发送数据,这当然会报错。。。。。

 
public boolean connectBlocking() throws InterruptedException {
		connect();
		connectLatch.await();
		return engine.isOpen();
	}

 

 


感谢各位!请认准中国驰名品牌哦~
谢谢各位老铁支持~

 

 

  • 12
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 15
    评论
Android中接入WebSocket可以通过以下步骤进行操作: 1. 创建一个WebSocket连接:你可以通过使用WebSocket库(如OkHttp或Java-WebSocket)来创建一个WebSocket连接。在Android中,通常会在应用的网络层或后台服务中创建WebSocket连接。你可以在应用的主线程或者使用异步线程来创建WebSocket连接。 2. 初始化WebSocket连接:在创建WebSocket连接后,你需要初始化WebSocket连接。在你的代码中,你可以使用initSocket()函数来初始化WebSocket连接。在initSocket()函数中,你可以设置连接的URL、添加监听器以接收消息、实现心跳检测等功能。 3. 建立长连接并接收消息:一旦WebSocket连接初始化完成,你可以调用WebSocket的connect()方法来建立长连接。建立连接后,你可以使用onMessage()方法来接收服务器发送的消息。你可以在onMessage()方法中处理接收到的消息,并在应用的界面或逻辑中进行相应的操作。 总结起来,为了在Android中接入WebSocket,你需要创建一个WebSocket连接,初始化连接并建立长连接,然后接收和处理来自服务器的消息。你可以使用相应的库和方法来实现这些功能。 引用中提到了如何通过WebSocket建立一个长连接,并接收来自服务器的消息。引用和中给出了示例代码,展示了如何在Android的代码中创建WebSocket连接和初始化连接。你可以根据这些示例来编写自己的代码,实现Android中的WebSocket接入。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [android接入简单的websocket步骤,建立一个长连接(带心跳检测)从服务器端接收消息](https://blog.csdn.net/qq_37328546/article/details/106565818)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值