牛骨文教育服务平台(让学习变的简单)
博文笔记

Android+ThinkPHP(后台)实现用户登录功能

创建时间:2016-08-25 投稿人: 浏览次数:1461

本文主要实现了Android客户端和服务器间的交互,客户端采用Android Studio开发,Web服务器采用PhpStorm开发,数据库使用MySQL,采用ThinkPHP框架开发,目前ThinkPHP最新的版本是ThinkPHP 5.0 RC4版本,本文中采用它的稳定版ThinkPHP3.2.2完整版,官网地址为:http://www.thinkphp.cn/。

开发前准备:

Android客户端:
服务端和客户端主要采用json格式的数据类型,目前比较好用的Json框架有google的gson以及阿里的fastjson,本文中选用fastjson框架来解析json数据;另外由于客户端存在网络请求,而目前okhttp是不错的网络请求框架,所以在本文中选用okhttp作为网络框架。

服务器端:
服务器的环境搭建可以选择XAMPP或者WAMPserver,基本上都是傻瓜式的一键安装,即包含有windows版也有Linux版本,如果是需要部署到服务器主机上,可以利用Xshell 5以及Xftp 5工具,具体过程也比较简单,这里就不再赘述。

数据库:
在MySql中新建一个叫login的数据库,并在该数据库下创建一个名叫login_user的数据表,该表包含有id、username、password、sex四个字段。创建数据表的sql语句如下:

CREATE TABLE `login`.`login_user` ( `id` INT NOT NULL AUTO_INCREMENT COMMENT "用户ID" , `username` VARCHAR(20) NOT NULL COMMENT "用户名" , `password` VARCHAR(40) NOT NULL COMMENT "用户密码" , `sex` TINYINT NOT NULL DEFAULT "1" COMMENT "性别(1:男性,0:女性)" , PRIMARY KEY (`id`)) ENGINE = InnoDB CHARACTER SET utf8 COLLATE utf8_general_ci COMMENT = "用户表";

Android客户端:
第一步 在Android studio中创建一个LoginTest的工程项目,然后通过Gradle添加前面提到的依赖库,同时在AndroidMainefest配置文件中添加上网络权限。
第二步 创建一个User的类,代码如下:

import java.io.Serializable;

/**
 * Created by Administrator on 2016/8/25.
 */
public class User implements Serializable
{
    private int id;
    private String username;
    private String password;
    private int sex;

    public int getId() {
        return id;
    }

    public void setId(String id) {
        this.id = Integer.parseInt(id);
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public int getSex()
    {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = Integer.parseInt(sex);
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username="" + username + """ +
                ", password="" + password + """ +
                ", sex=" + sex +
                "}";
    }
}

第三部 实现登陆页面的布局以及登陆Activity的代码编辑,由于代码比较简单,也很好理解,这里直接上代码了。
布局文件:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:layout_centerVertical="true"
        android:layout_marginLeft="20dp"
        android:layout_marginRight="20dp"
        android:background="#1f1100ff"
        >
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center_horizontal"
            >
            <TextView
                android:layout_width="60dp"
                android:layout_height="wrap_content"
                android:text="用户名"
                />
            <EditText
                android:id="@+id/id_tv_username"
                android:layout_width="200dp"
                android:layout_height="wrap_content"
                />
        </LinearLayout>
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center_horizontal"
            android:layout_marginTop="5dp"
            >
            <TextView
                android:layout_width="60dp"
                android:layout_height="wrap_content"
                android:text="密码"
                />
            <EditText
                android:id="@+id/id_tv_password"
                android:layout_width="200dp"
                android:layout_height="wrap_content"
                />
        </LinearLayout>
        <Button
            android:layout_marginTop="10dp"
            android:layout_marginBottom="10dp"
            android:layout_width="260dp"
            android:layout_height="30dp"
            android:background="#1f00ff00"
            android:text="登录"
            android:layout_gravity="center_horizontal"
            android:onClick="login"
            />
    </LinearLayout>
</RelativeLayout>

MainActivity:

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

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

import java.io.IOException;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

public class MainActivity extends AppCompatActivity
{
   EditText usernameTV;
   EditText passwordTV;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        usernameTV= (EditText) findViewById(R.id.id_tv_username);
        passwordTV= (EditText) findViewById(R.id.id_tv_password);
    }
   private static int SUCCESS=0x123;
   private static int ERROR=0x124;
    Handler mHandler=new Handler(){  //Handler方式实现子线程和主线程间的通信
        @Override
        public void handleMessage(Message msg)
        {
           if (SUCCESS==msg.what)
           {
               User user= (User) msg.obj;
               showToast(user.getUsername()+",你好!");
           }
            else if (ERROR==msg.what)
           {
               String info= (String) msg.obj;
               showToast(info);
           }
        }
    };
    /*
    登陆按钮点击响应触发该方法
    */
    public void login(View v)
    {
        String username = usernameTV.getText().toString().trim();
        String password = passwordTV.getText().toString().trim();
        if (username.length()>0&&password.length()>0)
        {
            String baseUrl="http://115.156.196.81:8088/login/index.php/Home/Index/login?";
            String url=baseUrl+"username="+username+"&password="+password;
            OkHttpClient client=new OkHttpClient();
            Request request=new Request.Builder().url(url).get().build();
            client.newCall(request).enqueue(new Callback()
            {
                @Override
                public void onFailure(Call call, IOException e)
                {
                    Message msg=new Message();
                    msg.what=ERROR;
                    msg.obj="网络请求失败";
                    mHandler.sendMessage(msg);
                }

                @Override
                public void onResponse(Call call, Response response) throws IOException
                {
                    if (response.isSuccessful())
                    {
                        String info = response.body().string();//获取服务器返回的json格式数据
                        Log.e("TAG", "onResponse: "+info );
                        JSONObject jsonObject = JSON.parseObject(info);//获得一个JsonObject的对象
                        int code = jsonObject.getObject("code", Integer.class);
                        if (200==code)//如果code等于200,则说明存在该用户,而且服务器还返回了该用户的信息
                        {
                            User user = jsonObject.getObject("data", User.class);//取出用户信息
                            Message msg=new Message();
                            msg.what=SUCCESS;
                            msg.obj=user;
                            mHandler.sendMessage(msg);
                        }
                        else
                        {
                            Message msg=new Message();
                            msg.what=ERROR;
                            msg.obj="用户名或者密码错误";
                            mHandler.sendMessage(msg);
                        }

                    }
                }
            });
        }
        else
        {
            showToast("用户名或者密码为空");
        }
    }
    /*
    以Toast的方式显示提示信息
    */
    public void showToast(String info)
    {
        Toast.makeText(this,info,Toast.LENGTH_SHORT).show();
    }
}

接下来是服务端的开发
ThinkPHP框架的搭建可以参考官方的参考手册,因为这里我们只开发APP后台的部分,只需要在Common目录下配置好数据库的信息,在Home模块下的Controller目录下默认有一个名为IndexController的控制器,我们可以自己创建一个新的控制器也可以直接在这个默认的控制器下编写登陆验证的后台代码。另外由于需要将我们的数据封装成json格式,所以需要对从数据库端获取的数据进行json的编码,下面给出以前写的一个json封装的类Response的代码。这个类可以将数据封装成json或者xml格式的形式。
Response.php

<?php

/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2016/4/7
 * Time: 17:17
 */
class Response
{
    public static function show($code,$message="",$data=array(),$type="json")
    {
        if(!is_numeric($code))
        {
            return;
        }
        $type=isset($_GET["format"])?$_GET["format"]:"json";
        if($type=="json")
        {
          return  self::json($code,$message,$data);
        }
        elseif($type=="xml")
        {
         return    self::xml($code,$message,$data);
        }
    }
    /*
     *按Json格式输出传输数据
     * $code 状态码
     * $message 提示信息
     *$data array 数据
     *return json字符串
     * */
    public static function  json($code,$message="",$data=array())
    {
          if(!is_numeric($code))
          {
             return;
          }
         $result=array
         (
             "code"=>$code,
             "message"=>$message,
             "data"=>$data
         );
        echo json_encode($result);
    }
    public static  function xml($code,$message="",$data=array())
    {
        if(!is_numeric($code)) {
            return "";
        }

        $result = array(
            "code" => $code,
            "message" => $message,
            "data" => $data
        );

        header("Content-Type:text/xml");
        $xml = "<?xml version="1.0" encoding="UTF-8"?>
";
        $xml .= "<root>";
        $xml .= self::xmlToEncode($result);
        $xml .= "</root>";
        echo $xml;
    }
    public static  function xmlToEncode($result)
    {
        $xml = $attr = "";
        foreach($result as $key => $value)
        {
            if(is_numeric($key))
            {
                $attr = " id="" . $key . """;
                $key = "item";
            }
            $xml .= "<{$key}{$attr}>";
            $xml .= is_array($value) ? self::xmlToEncode($value) : $value;
            $xml .= "</{$key}>
";
        }
        return $xml;
    }
}

注意:将该文件一定要放在IndexController.class.php同级目录下。
接下来给出IndexController.class.php中的代码

<?php
namespace HomeController;
use ThinkController;
require_once("Response.php");//引用Response类
class IndexController extends Controller
{
    public function login($username,$password)
    {
        $userModel=M("User");
        $where["username"]  = array("eq", $username);
        $where["password"]  = array("eq",$password);//实际的项目一般密码都会采用MD5算法进行加密
        $result= $userModel->where($where)->find();
        if(empty($result))//如果找不到数据,code=400
        {
            Response::show(400,"用户名或者密码错误",array());
        }
        else
        {
            Response::show(200,"登录成功",$result);
        }
    }
}

至此,一个简单的利用ThinkPHP框架作为APP登陆后台的应用开发就完成了,是不是很简单呢?本文也只是简单的介绍了下ThinkPHP框架如何实现APP后台开发的功能,如果将后台部署到本地主机上,可以手机可以通过随身wifi共享的局域网络访问IP地址的形式访问后台,但是如需像一般的应用那样在全网上访问的话,需要部署到服务器主机上,目前比较好用的云服务器有腾讯云和阿里云,腾讯云有一个校园计划,一元钱就能享受到1M的带宽的云服务器,对学生族来说是莫大的好消息。

测试中数据库中login_user只有一条记录的 username:风中的歌 password:123456789

用户名 密码正确验证时

这里写图片描述

用户名 密码验证失败时

这里写图片描述

网络异常时

这里写图片描述

声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。