这完全是凭借我自己的看法实现的。因为我发现有的人是把数据存储再Android本地数据库里的,我就不想在本地再新建一个数据库了,直接在需要的时候直接向服务器请求数据。

前一篇文章已经把服务器端的登录搞定了。现在是Android这边的http请求的发出和处理返回的数据,然后进行界面的显示。

这里要注意一个编码得问题,就是安卓这边收发数据使用得是什么编码,然后服务器这边收发数据又是什么编码,这里我们需要把编码全都设置位utf-8编码格式。 不过如果不出现中文的话,编码什么的问题不大,因为ASCII码大家都兼容。所以出了问题再说。

在调试的时候发现: ipconfig出来




android登录服务器界面 安卓登录服务器软件_ssm登录功能实现


下面是wires hark的选项


android登录服务器界面 安卓登录服务器软件_android_02


这里有两个以太网网卡,然后我想抓模拟器的包(虚拟机3),发现抓不到发出去的http。然后转念一想,直接去抓以太网网卡的包,然后就抓到了。

这里遇到了几个问题。这里记录一下,估计是新手常见错误:

  1. AndroidManifest.xml 文件里没有加

<uses-permission android:name="android.permission.INTERNET"/>

也就是需要访问网络资源,但是你没有给它访问网络资源的权限。现象就是 没反应,程序进行到网络连接部分就进行不了了,但是又没有什么报错。 很难受,然后各种调试。。。。还是自己基础太差了。。

2.连接网络的子线程不能使用


Toast.makeText(getApplicationContext(), "输入"+username+" "+password, Toast.LENGTH_SHORT).show();


进行调试,这个会出现app闪退的情况,然后报:


android登录服务器界面 安卓登录服务器软件_数据_03


的错误,即 “很抱歉, xxx已停止运行”。


这位大哥里说的:

在安卓开发环境下,由于主线程不能进行网络访问,因此需要在开启一个子线程向服务器提交数据。为了更加直观的观察数据,可以在程序屏幕上显示服务器反馈信息。又由于子线程无法更改UI界面,因此需要引入Handler代理器(也就是说,在这个handler里可以实现UI界面的更改)。实现get/post提交基本步骤就是,获取URL路径,根据路径得到Http连接,用HttpURLConnection对象设置相关的http配置信息、提交方式以及获取反馈码。当响应码为200时表示提交成功,可以通过HttpURLConnection以流的形式获取反馈信息。

我应该就是由于在子线程里更改UI界面了,所以报错了。

然后也是用wireshark调试了一波。。花费了不少时间。然后忽然记起来wires hark不能抓自己发给自己的包,只能抓往外的包。。 rawcap可以 。参考 :

何柄融:netty的半包和黏包现象的底层深度剖析 tcp的粘包拆包理论 RawCap抓自己发给自己的包zhuanlan.zhihu.com


即可。

下面是app上成功进行访问后的第一次,这个是直接把返回的数据写在了账号框里,这样调试着方便。(我这里是code=100表示成功,200表示失败。)


android登录服务器界面 安卓登录服务器软件_服务器_04


下面是浏览器上的,可以进行对比:


android登录服务器界面 安卓登录服务器软件_数据_05


然后是服务器端的输出:


android登录服务器界面 安卓登录服务器软件_ssm登录功能实现_06


一切现在都连接起来了。

现在是模拟器是客户端,本地电脑是服务端。然后app连接的服务器地址是本地的ipv4地址。即使不同网段什么的都没影响,都是可以连接的。

把此刻的程序贴出来吧,GitHub上传比较完善一点的比较好。


public class MainActivity extends AppCompatActivity {

    private  Button loginButton;
    private Handler handler; // 声明一个Handler对象
    private String result = "";	//声明一个代表显示内容的字符串
    private EditText  usernameText;
    String username;
    String password;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        loginButton=findViewById(R.id.loginButton);
        loginButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                usernameText=findViewById(R.id.username);
                EditText passwordText=findViewById(R.id.password);
                username=usernameText.getText().toString();
                password=passwordText.getText().toString();
                Toast.makeText(getApplicationContext(), "输入"+username+" "+password, Toast.LENGTH_SHORT).show();
                // 创建一个新线程,用于发送并读取微博信息
                new Thread(new Runnable() {
                    public void run() {
                        send();	//发送文本内容到Web服务器
                        Message m = handler.obtainMessage(); // 获取一个Message
               //         Toast.makeText(getApplicationContext(), "message"+m, Toast.LENGTH_SHORT).show();
                        handler.sendMessage(m); // 发送消息
                    }
                }).start(); // 开启线程
            }
        });

        handler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                if (result != null) {
                    Toast.makeText(getApplicationContext(), "返回"+result, Toast.LENGTH_SHORT).show();
                    usernameText.setText(result);
                }
                super.handleMessage(msg);
            }
        };
    }

    public void send() {
       // Toast.makeText(getApplicationContext(), " go in send ", Toast.LENGTH_SHORT).show();
        String target="";
        target = "http://175.10.104.21/login?username="+username.trim()+"&password="+password.trim();	//要访问的URL地址
        URL url;
        try {
            url = new URL(target);
            HttpURLConnection urlConn = (HttpURLConnection) url
                    .openConnection();	//创建一个HTTP连接
            InputStreamReader in = new InputStreamReader(
                    urlConn.getInputStream()); // 获得读取的内容
            BufferedReader buffer = new BufferedReader(in); // 获取输入流对象
            String inputLine = null;
            //通过循环逐行读取输入流中的内容
            while ((inputLine = buffer.readLine()) != null) {
                result += inputLine + "n";
            }
            //Toast.makeText(getApplicationContext(), "result "+result, Toast.LENGTH_SHORT).show();
            in.close();	//关闭字符输入流对象
            urlConn.disconnect();	//断开连接
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}


然后是xml的:


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:orientation="vertical"
    android:gravity="center"
    tools:context=".MainActivity">

    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingBottom="20dp"
        android:drawableLeft="@mipmap/zhanghao"
        android:id="@+id/username" />
    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingBottom="20dp"
        android:hint="  密码"
        android:inputType="textPassword"
        android:drawableLeft="@mipmap/mima"
        android:id="@+id/password" />
    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="登录"
        android:textColor="#FFFFFF"
        android:background="#FF009688"
        android:id="@+id/loginButton" />
</LinearLayout>


最后注意:下面这个网络权限允许的位置即可。


android登录服务器界面 安卓登录服务器软件_android登录服务器界面_07


然后现在把它完善起来。加上界面跳转、服务器返回数据解析之类的。


android登录服务器界面 安卓登录服务器软件_ssm登录功能实现_08


看着自己这开的一堆东西就怕。。幸好台式机带得动。。。没有成为累赘。。

我们得到服务器返回的数据之后,要先判断登录是否成功,然后再进行界面跳转。

所以要使用Gson进行json数据的解析,然后进行判断。


这篇文章进行的gson使用。这里学习了Android的jar包添加,然后是grade文件的配置,然后

Gson gson=new Gson(); 创建对象,fromJson是字符串转对象,toJson是对象转字符串。处理器的代码如下


handler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                if (result != null) {

                    Gson gson=new Gson();
                    Msg message=gson.fromJson(result,Msg.class);
                    if(message.code==100){
                        Toast.makeText(getApplicationContext(), "登录成功,进行跳转", Toast.LENGTH_SHORT).show();
                    }else{
                        usernameText.setText("error number");
                    }

                }
                super.handleMessage(msg);
            }
        };


这样点击登录后即可正常返回code=100,然后进行输出。

可是再点击一次登录就app闪退报错了。这里不太理解Android里面的线程模型,也不知道哪里出错了,欢迎指出问题。

然后是获得数据确认成功后进行跳转: 下面是跳转成功界面:


android登录服务器界面 安卓登录服务器软件_android登录服务器界面_09


到这里上传一次github吧。

由于对github操作比较差,现在就不搞它先了。直接上传zip来得简单。还是太菜了。

源码如下 :

https://github.com/jackhbr/--stm32f4-/blob/master/main.zipgithub.com


后面就是app在新界面里发送请求获得正常网关的数据。此时服务器端也要加代码了。

欢迎交流讨论。