#1 - 2017-10-12 13:10
東瀬まつり🦋❄️🐻💎🐺🍎🐠 ([s]安静点格子[/s] ☄️⚓ ☁️⭐️)
我按照网上的教程写了一个socket测试程序

socket服务器用php脚本写的在运行     √
在新线程里进行网络操作                     √
在AndroidMainFast里添加网络权限     √

但是不知道为什么每次线程执行到socket = new socket(host,ip)的时候就卡住了,按步执行走到那里也不知道光标跳到那里去了...(bgm42)然后点发送的时候socket还是null自然程序就闪退了...

和同学搞创新项目打算做一个基于地图的留言探索app,都是安卓初心者也不知道通信方法是用socket还是http还是别的什么好,想求一些建议(bgm33)(安卓上的socket有轮子吗?)

附上code
package moe.azusebox.socket_test_app_50;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;


public class MainActivity extends AppCompatActivity implements Runnable {

    //定义相关变量,完成初始化
    private TextView txtshow;
    private EditText editsend;
    private Button btnsend;
    private static final String HOST = "45.32.20.244";
    private static final int PORT = 110;
    private Socket socket = null;
    private BufferedReader in = null;
    private PrintWriter out = null;
    private String content = "";
    private StringBuilder sb = null;

    //定义一个handler对象,用来刷新界面
    public Handler handler = new Handler() {
        public void handleMessage(Message msg) {
            if (msg.what == 0x123) {
                sb.append(content);
                txtshow.setText(sb.toString());
            }
        }

        ;
    };


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        sb = new StringBuilder();
        txtshow = (TextView) findViewById(R.id.txtshow);
        editsend = (EditText) findViewById(R.id.editsend);
        btnsend = (Button) findViewById(R.id.btnsend);

        //当程序一开始运行的时候就实例化Socket对象,与服务端进行连接,获取输入输出流
        //因为4.0以后不能再主线程中进行网络操作,所以需要另外开辟一个线程
        new Thread() {

            public void run() {
                try {
                    socket = new Socket(HOST, PORT);//就是这一步mmp
                    in = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
                    out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(
                            socket.getOutputStream())), true);
                } catch (IOException e) {
                    e.printStackTrace();//而且并不会throw任何东西
                }
            }
        }.start();

        //为发送按钮设置点击事件
        btnsend.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                String msg = editsend.getText().toString();
                if(socket == null)
                {
                    Toast.makeText(getApplicationContext(),"socket initiate failed, retrying",Toast.LENGTH_SHORT).show();
                    new Thread() {

                        public void run() {
                            try {
                                socket = new Socket(HOST, PORT);
                                in = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
                                out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(
                                        socket.getOutputStream())), true);
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                    }.start();
                }
                else
                {
                    if (socket.isConnected()) {
                        if (!socket.isOutputShutdown()) {
                            out.println(msg);
                        }
                    }
                }
            }
        });
        new Thread(MainActivity.this).start();
    }

    //重写run方法,在该方法中输入流的读取
    @Override
    public void run() {
        try {
            while (true) {
                if (socket.isConnected()) {
                    if (!socket.isInputShutdown()) {
                        if ((content = in.readLine()) != null) {
                            content += "\n";
                            handler.sendEmptyMessage(0x123);
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
#2 - 2017-10-12 13:14
(もうぅ!プラチナむかつく!)
全bgm只有我不是码农系列 (bgm38)
#3 - 2017-10-13 00:01
#3-1 - 2017-10-15 01:18
東瀬まつり🦋❄️🐻💎🐺🍎🐠
emmmm谢谢!好多好玩的轮子!
#4 - 2017-10-13 00:14
(想和可爱的纸片小男孩贴贴)
强烈推荐retrofit2+Django REST framework
超简单超方便还算优雅,而且新手的app应该也不用考虑生产环境,直接django直接runserver就能跑。python也是很简单的语言会java很好上手。
#4-1 - 2017-10-13 00:20
发光的球
当然要全java的话,java也有很多REST框架,可以选轻量级的看看。
#4-2 - 2018-3-14 10:49
stormynight
谢谢推荐,php看得一头雾水决定还是换成python了
#5 - 2017-10-15 02:31
(讓一切都自動化!)
好奇問問,為何要 socket?普通需求的話 HTTP 就能勝任吧
#5-1 - 2017-10-15 23:14
fantasy
+1
#5-2 - 2017-10-17 00:59
東瀬まつり🦋❄️🐻💎🐺🍎🐠
我也不清楚socket和http哪个更合适,然后教程里先写了socket就准备试试没想到上来就踩坑了(bgm38)
#5-3 - 2017-10-18 11:29
Franklin Yu
東瀬まつり太 说: 我也不清楚socket和http哪个更合适,然后教程里先写了socket就准备试试没想到上来就踩坑了
要持續通信、性能要求高的用 socket,否則用 HTTP。一般來說用 socket 的話感覺要手動序列化,比如 Protocol Buffers 或者 BSON 之類。Wiki: comparison of data serialization formats
#6 - 2017-10-15 20:45
(随性和严谨比较起来的话,果然还是随性一点比较好 ... . ...)
无状态通信协议当然要上http
#7 - 2017-10-15 21:56
((((;゚Д゚)))))))
firebase啊(x
#8 - 2017-10-15 22:06
(bgm38)通信啊 反正我只用过socket
#8-1 - 2017-10-17 01:02
東瀬まつり🦋❄️🐻💎🐺🍎🐠
socket看着感觉上手超容易(并不(bgm38)
#9 - 2017-10-16 12:45
(test)
很普通的http就行了
各种httpclient框架,最常用的是httpclient了,不过安卓端很多都在用okhttp retrofit之类
最近我在服务端也开始用okhttp了,我这边的应用来看,默认配置下性能比httpclient要好很多
#10 - 2018-3-14 11:40
(hhh汝视视汝)
如果对网络和性能没特殊要求,比较省事的选择是单向的http,双向的websocket (都是message based)
#11 - 2018-3-14 13:09
(誰か散らせ 僕がここに居たという証も ...)
不需要持续通讯就用REST好了
我猜你的App主要是在地图上留言
应该是用不上socket的

以我的认知,只有股票持续报价、MMORPG之类才用socket