使用PHP MySQL进行Android登录和注册
Android登录和注册是非常常见的场景。
您会在所有需要用户信息的应用程序中找到注册和登录操作。
在本教程中,我们将设置本地Web服务器和MySQL数据库。
我们将开发android登录和注册应用程序。
我们将使用PHP脚本连接到MySQL数据库。
Android登录注册
第一步是创建后端Web服务器。
我在Mac OS X上工作,并且XAMPP可用于快速设置本地Apache Web服务器和MySQL数据库。
设置XAMPP服务器
XAMPP(或者WAMP)是一键式安装程序软件,可为开发PHP,MySQL Web应用程序(我们将与android应用程序连接)创建环境。
从这里下载并安装XAMPP。
安装后启动XAMPP应用程序,将会看到下面的屏幕。
您可以通过打开" https://localhost"来测试您的服务器。
应出现以下屏幕。
另外,您可以通过打开https://localhost/phpmyadmin
来检查phpMyAdmin。
似乎MySQL服务器无法正常运行。
转到XAMPP应用程序中的"管理服务器"选项卡,然后单击"全部重新启动"。
如下图所示,服务器应正常运行。
现在在本地主机上测试phpMyAdmin,您将得到一个类似于此的屏幕。
现在,让我们测试一个示例php脚本。
创建一个新的test.php
文件,并其中添加以下几行。
<?php echo "Hello, World"; ?>
在上面的代码中:
php开始为任何PHP脚本打开标签。
?>表示结束标记,例如Java中的结束括号。
注意:本教程不是必须了解PHP。
如果您使用的是MAC,请转到"应用程序"->" Xampp"->" htdocs"。
在这里创建一个新文件夹,假设为test_android并复制粘贴之前创建的test.php。
现在打开URLhttps://localhost/test_android/test.php
您最终将看到如下屏幕:
设置MySQL数据库
通过访问https://localhost/phpmyadmin
打开phpMyAdmin。
现在,选择标题行左上方的"数据库"标签。
给出一个随机名称并创建它。
新创建的空数据库将在左侧边列中可见。
让我们在新创建的数据库中创建一个用户表。
在控制台中运行以下查询
CREATE TABLE `firstDB`.`users` ( `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY , `username` VARCHAR( 20 ) NOT NULL , `password` VARCHAR( 20 ) NOT NULL )
将PHP连接到MySQL数据库
要将PHP脚本连接到MySQL数据库,需要三个输入值。
以下是输入以及XAMPP服务器的默认值
- 主机名:localhost
- MySQL用户名:root
- MySQL密码:空白。
让我们创建一个test-connect.php脚本,并将其添加到htdocs-> test-android文件夹中。
<?php $host="localhost"; $user="root"; $password=""; $con=mysql_connect($host,$user,$password); if($con) { echo '<h1>Connected to MySQL</h1>'; } else { echo '<h1>MySQL Server is not connected</h1>'; } ?>
mysql_connect()是PHP的内置函数,可使用上述参数连接到MySQL数据库。
尝试运行https://localhost/test_android/test-connect.php
并查看输出。
如果未连接,请尝试重新启动XAMPP服务器。
Android登录注册应用
现在,我们已经讨论了PHP和MySQL的基本设置,让我们进入android登录应用程序部分。
我们将开发一个登录/注册应用程序。
为了简单明了,我们将在注册过程中检查用户名和电子邮件是否唯一。
在进入应用逻辑之前,让我们先研究PHP脚本和MySQL数据库。
首先,让我们删除Table用户,并在上述应用程序的上下文中创建一个新用户。
CREATE TABLE IF NOT EXISTS `firstDB`.`users` ( `id` int(20) NOT NULL AUTO_INCREMENT PRIMARY KEY, `username` varchar(70) NOT NULL, `password` varchar(40) NOT NULL, `email` varchar(50) NOT NULL, `created_at` datetime NOT NULL, `updated_at` datetime DEFAULT NULL )
以下是您可以复制粘贴到htdocs-> test_android文件夹中的PHP脚本。
config.php
<?php define("DB_HOST", "localhost"); define("DB_USER", "root"); define("DB_PASSWORD", ""); define("DB_NAME", "firstDB"); ?>
下面给出了数据库连接的脚本。
db-connect.php
<?php include_once 'config.php'; class DbConnect{ private $connect; public function __construct(){ $this->connect = mysqli_connect(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME); if (mysqli_connect_errno($this->connect)){ echo "Unable to connect to MySQL Database: " . mysqli_connect_error(); } } public function getDb(){ return $this->connect; } } ?>
以下脚本包含应用程序的所有核心功能。
user.php
<?php include_once 'db-connect.php'; class User{ private $db; private $db_table = "users"; public function __construct(){ $this->db = new DbConnect(); } public function isLoginExist($username, $password){ $query = "select * from ".$this->db_table." where username = '$username' AND password = '$password' Limit 1"; $result = mysqli_query($this->db->getDb(), $query); if(mysqli_num_rows($result) > 0){ mysqli_close($this->db->getDb()); return true; } mysqli_close($this->db->getDb()); return false; } public function isEmailUsernameExist($username, $email){ $query = "select * from ".$this->db_table." where username = '$username' AND email = '$email'"; $result = mysqli_query($this->db->getDb(), $query); if(mysqli_num_rows($result) > 0){ mysqli_close($this->db->getDb()); return true; } return false; } public function isValidEmail($email){ return filter_var($email, FILTER_VALIDATE_EMAIL) !== false; } public function createNewRegisterUser($username, $password, $email){ $isExisting = $this->isEmailUsernameExist($username, $email); if($isExisting){ $json['success'] = 0; $json['message'] = "Error in registering. Probably the username/email already exists"; } else{ $isValid = $this->isValidEmail($email); if($isValid) { $query = "insert into ".$this->db_table." (username, password, email, created_at, updated_at) values ('$username', '$password', '$email', NOW(), NOW())"; $inserted = mysqli_query($this->db->getDb(), $query); if($inserted == 1){ $json['success'] = 1; $json['message'] = "Successfully registered the user"; }else{ $json['success'] = 0; $json['message'] = "Error in registering. Probably the username/email already exists"; } mysqli_close($this->db->getDb()); } else{ $json['success'] = 0; $json['message'] = "Error in registering. Email Address is not valid"; } } return $json; } public function loginUsers($username, $password){ $json = array(); $canUserLogin = $this->isLoginExist($username, $password); if($canUserLogin){ $json['success'] = 1; $json['message'] = "Successfully logged in"; }else{ $json['success'] = 0; $json['message'] = "Incorrect details"; } return $json; } } ?>
在上面的代码中,$json包含返回的JSONObjects。
以下PHP脚本是首先从应用程序中调用的脚本。
index.php
<?php require_once 'user.php'; $username = ""; $password = ""; $email = ""; if(isset($_POST['username'])){ $username = $_POST['username']; } if(isset($_POST['password'])){ $password = $_POST['password']; } if(isset($_POST['email'])){ $email = $_POST['email']; } $userObject = new User(); //Registration if(!empty($username) && !empty($password) && !empty($email)){ $hashed_password = md5($password); $json_registration = $userObject->createNewRegisterUser($username, $hashed_password, $email); echo json_encode($json_registration); } //Login if(!empty($username) && !empty($password) && empty($email)){ $hashed_password = md5($password); $json_array = $userObject->loginUsers($username, $hashed_password); echo json_encode($json_array); } ?>
在上面的代码中,我们检查电子邮件字段是否为空。
如果是这样,我们将在PHP脚本中调用登录功能,否则,我们将转到注册功能。
JSON响应返回两个参数:success(0或者1)和消息。
" md5()"函数使用RSA Data Security,Inc. MD5消息摘要算法来创建密码的哈希字符串。
为了检查电子邮件地址是否有效,我们实现了一个" isValidEmail()"方法。
FILTER_VALIDATE_EMAIL适用于PHP版本5.2.0+
Android登录注册项目结构
在此项目中,我们使用了三个库来在我们的应用程序中实现HTTP调用。
JSONParser类用于对本地主机进行POST和GET HTTP调用,并以JSONObject的形式返回响应。
Android登录注册码
下面定义了" activity_main.xml"布局。
<?xml version="1.0" encoding="utf-8"?> <ScrollView xmlns:android="https://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:fillViewport="true"> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_centerInParent="true" android:paddingLeft="24dp" android:paddingRight="24dp" android:id="@+id/linearLayout"> <EditText android:id="@+id/editName" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Username" android:textColor="#FF192133" android:textColorHint="#A0192133" android:fontFamily="sans-serif-light" android:focusable="true" android:focusableInTouchMode="true" <EditText android:id="@+id/editPassword" android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="textPassword" android:textColor="#FF192133" android:textColorHint="#A0192133" android:fontFamily="sans-serif-light" android:hint="Password" android:focusable="true" android:focusableInTouchMode="true" <EditText android:id="@+id/editEmail" android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="textEmailAddress" android:textColor="#FF192133" android:visibility="gone" android:textColorHint="#A0192133" android:fontFamily="sans-serif-light" android:hint="Email" android:focusable="true" android:focusableInTouchMode="true" <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/btnSignIn" android:text="SIGN IN" android:textStyle="bold" <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/btnRegister" android:text="REGISTER" android:textStyle="bold" </LinearLayout> </RelativeLayout> </ScrollView>
MainActivity.java在下面给出。
package com.theitroad.loginphpmysql; import android.content.Intent; import android.content.SharedPreferences; import android.graphics.Color; import android.os.AsyncTask; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; import org.apache.http.NameValuePair; import org.apache.http.message.BasicNameValuePair; import org.json.JSONException; import org.json.JSONObject; import java.util.ArrayList; public class MainActivity extends AppCompatActivity { EditText editEmail, editPassword, editName; Button btnSignIn, btnRegister; String URL= "https://10.0.3.2/test_android/index.php"; JSONParser jsonParser=new JSONParser(); int i=0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); editEmail=(EditText)findViewById(R.id.editEmail); editName=(EditText)findViewById(R.id.editName); editPassword=(EditText)findViewById(R.id.editPassword); btnSignIn=(Button)findViewById(R.id.btnSignIn); btnRegister=(Button)findViewById(R.id.btnRegister); btnSignIn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { AttemptLogin attemptLogin= new AttemptLogin(); attemptLogin.execute(editName.getText().toString(),editPassword.getText().toString(),""); } }); btnRegister.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if(i==0) { i=1; editEmail.setVisibility(View.VISIBLE); btnSignIn.setVisibility(View.GONE); btnRegister.setText("CREATE ACCOUNT"); } else{ btnRegister.setText("REGISTER"); editEmail.setVisibility(View.GONE); btnSignIn.setVisibility(View.VISIBLE); i=0; AttemptLogin attemptLogin= new AttemptLogin(); attemptLogin.execute(editName.getText().toString(),editPassword.getText().toString(),editEmail.getText().toString()); } } }); } private class AttemptLogin extends AsyncTask<String, String, JSONObject> { @Override protected void onPreExecute() { super.onPreExecute(); } @Override protected JSONObject doInBackground(String... args) { String email = args[2]; String password = args[1]; String name= args[0]; ArrayList params = new ArrayList(); params.add(new BasicNameValuePair("username", name)); params.add(new BasicNameValuePair("password", password)); if(email.length()>0) params.add(new BasicNameValuePair("email",email)); JSONObject json = jsonParser.makeHttpRequest(URL, "POST", params); return json; } protected void onPostExecute(JSONObject result) { //dismiss the dialog once product deleted //Toast.makeText(getApplicationContext(),result,Toast.LENGTH_LONG).show(); try { if (result != null) { Toast.makeText(getApplicationContext(),result.getString("message"),Toast.LENGTH_LONG).show(); } else { Toast.makeText(getApplicationContext(), "Unable to retrieve any data from server", Toast.LENGTH_LONG).show(); } } catch (JSONException e) { e.printStackTrace(); } } } }
那是一个很大的代码!让我们从以上代码中得出重要的推论。
https://10.0.3.2是localhost重新路由地址。
如果您使用的是Genymotion模拟器,则此地址专用。
将https://10.0.2.2用于AVD模拟器,现在已大大改进。
如果您使用计算机的WIFI地址在自己的设备上运行该应用程序,示例:https://192.168.0.143。单击"注册"按钮后,我们将以编程方式隐藏"登录"按钮并显示"电子邮件地址"输入文本字段。
AttemptLogin类在后台执行对本地主机的网络HTTP请求。
用户名密码和电子邮件参数将添加到通过makeHttpRequest(URL," POST",params)方法传递的ArrayList中; JSONParser类。
- 在onPostExecute方法中,我们在Toast消息中显示从服务器返回的消息字符串。
下面给出了JSONParser.java类。
package com.theitroad.loginphpmysql; import android.util.Log; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.NameValuePair; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.utils.URLEncodedUtils; import org.apache.http.impl.client.DefaultHttpClient; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import java.util.ArrayList; /** * Created by anupamchugh on 29/08/16. */ public class JSONParser { static InputStream is = null; static JSONObject jObj = null; static JSONArray jArr = null; static String json = ""; static String error = ""; //constructor public JSONParser() { } //function get json from url //by making HTTP POST or GET mehtod public JSONObject makeHttpRequest(String url, String method, ArrayList params) { //Making HTTP request try { //check for request method if(method.equals("POST")){ //request method is POST //defaultHttpClient HttpClient httpClient = new DefaultHttpClient(); HttpPost httpPost = new HttpPost(url); httpPost.setEntity(new UrlEncodedFormEntity(params)); try { Log.e("API123", " " +convertStreamToString(httpPost.getEntity().getContent())); Log.e("API123",httpPost.getURI().toString()); } catch (Exception e) { e.printStackTrace(); } HttpResponse httpResponse = httpClient.execute(httpPost); Log.e("API123",""+httpResponse.getStatusLine().getStatusCode()); error= String.valueOf(httpResponse.getStatusLine().getStatusCode()); HttpEntity httpEntity = httpResponse.getEntity(); is = httpEntity.getContent(); }else if(method.equals("GET")){ //request method is GET DefaultHttpClient httpClient = new DefaultHttpClient(); String paramString = URLEncodedUtils.format(params, "utf-8"); url += "?" + paramString; HttpGet httpGet = new HttpGet(url); HttpResponse httpResponse = httpClient.execute(httpGet); HttpEntity httpEntity = httpResponse.getEntity(); is = httpEntity.getContent(); } } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } try { BufferedReader reader = new BufferedReader(new InputStreamReader( is, "iso-8859-1"), 8); StringBuilder sb = new StringBuilder(); String line = null; while ((line = reader.readLine()) != null) { sb.append(line + "\n"); } is.close(); json = sb.toString(); Log.d("API123",json); } catch (Exception e) { Log.e("Buffer Error", "Error converting result " + e.toString()); } //try to parse the string to a JSON object try { jObj = new JSONObject(json); jObj.put("error_code",error); } catch (JSONException e) { Log.e("JSON Parser", "Error parsing data " + e.toString()); } //return JSON String return jObj; } private String convertStreamToString(InputStream is) throws Exception { BufferedReader reader = new BufferedReader(new InputStreamReader(is)); StringBuilder sb = new StringBuilder(); String line = null; while ((line = reader.readLine()) != null) { sb.append(line); } is.close(); return sb.toString(); } }
在上面的代码中,我们根据在makeHttpRequest函数中传递的第二个参数来调用相应的类HTTPPost或者HTTPGet。
jObj.put("error_code",error);
上面,我们将服务器返回的响应状态代码附加在返回给MainActivity类的最终JSONObject中。
注意:不要忘记在AndroidManifest.xml文件中添加以下权限。
<uses-permission android:name="android.permission.INTERNET"
许多用户已在本教程的底部发布了他们的注释,指出他们正在"无法检索数据" Toast。
请注意,从Android 6.0及更高版本开始,您需要在Manifest.xml文件的应用程序标记中添加以下属性:
android:usesCleartextTraffic =" true""
为什么这样?为了允许仿真器/设备的网络安全进行http调用。
请使用以下来自Android Q仿真器的最新屏幕抓图检查输出。
链接和我们的Github存储库中更新了具有AndroidManifest.xml文件中的更改的最新源代码。
实际应用程序的输出如下。
Android注册用户
在下面的屏幕截图中,我们注册了一个新用户,并将其添加到数据库中。
然后,我们使用在注册过程中输入的凭据登录。
Android登录与Php Mysql最终输出
这结束了使用PHP MySQL教程的Android登录。
您可以从下面的链接下载项目。
它还包含test_android文件夹,其中包含PHP文件。
将其复制到xampp-> htdocs文件夹中!