Androidアプリのログインと登録、PHPとMySQLを使用

Androidのログインと登録は非常に一般的なシナリオです。ユーザー情報が必要なすべてのアプリで、登録とログイン操作が見つかります。このチュートリアルでは、ローカルウェブサーバーとMySQLデータベースをセットアップします。Androidのログインと登録アプリケーションを開発します。MySQLデータベースに接続するためにPHPスクリプトを使用します。

アンドロイドのログイン登録

最初のステップはバックエンドのウェブサーバーを作成することです。私はMac OS Xで作業しており、XAMPPを使用してローカルのApacheウェブサーバーとMySQLデータベースを迅速にセットアップすることができます。

XAMPPサーバーのセットアップを行う

XAMPP(またはWAMP)は、PHP、MySQLウェブアプリケーションの開発環境を作成するためのワンクリックインストーラーソフトウェアです(Androidアプリケーションと接続する予定です)。ここからXAMPPをダウンロードしてインストールしてください。インストール後、XAMPPアプリを起動すると、以下の画面が表示されます。https://localhostを開くことでサーバーをテストすることができます。以下のような画面が表示されるはずです。また、https://localhost/phpmyadminを開くことでphpMyAdminを確認することができます。それでは見てみましょう!おっと!以下のような画面が表示されてしまうかもしれません。MySQLサーバーが正常に実行されていないようです。XAMPPアプリケーションの[サーバーの管理]タブに移動し、[全て再起動]をクリックしてください。以下の画像のように、サーバーは正常に実行されるはずです。今度はlocalhostでphpMyAdminをテストして、以下のような画面が表示されるはずです。それでは、サンプルのphpスクリプトをテストしてみましょう。新しいtest.phpファイルを作成し、以下の行を追加してください。

<?php
echo "Hello, World";
?>

上記のコードにおいて:

  • ?php starts opening tag for any PHP script.
  • ?> means closing tag like closing bracket in Java.

注意:このチュートリアルでは、PHPを知っている必要はありません。もしMACをお使いの場合は、Applications->Xampp->htdocsに移動してください。ここで新しいフォルダを作成し、例えばtest_androidと名付け、以前に作成されたtest.phpをコピーアンドペーストしてください。そして、次にhttps://localhost/test_android/test.phpというURLを開いてください。すると、次のような画面が表示されます。

MySQLデータベースのセットアップ

https://localhost/phpmyadmin にアクセスして phpMyAdmin を起動してください。次に、ヘッダーの一番左にある「データベース」タブを選択してください。適当な名前を入力し、作成してください。新しく作成された空のデータベースは、左側のサイドバーに表示されます。新しく作成したデータベースに「users」というテーブルを作成しましょう。以下のクエリをコンソールで実行してください。

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データベースに接続するためには、3つの入力値が必要です。以下に、XAMPPサーバーのための入力とそのデフォルト値を示します。

  • Host name: localhost
  • MySQL user name : root
  • MySQL password : It is blank. “”

htdocs->test-androidフォルダにtest-connect.phpスクリプトを作成して追加しましょう。

<?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()は、上記にリストアップされたパラメータを使用してMySQLデータベースに接続するためのPHPの組み込み関数です。https://localhost/test_android/test-connect.phpを実行して、その出力を確認してください。接続されていない場合は、XAMPPサーバーを再起動してみてください。

アンドロイドログイン登録アプリ

PHPとMySQLの基本的なセットアップについて話し合ったので、Androidのログインアプリケーションの部分に入りましょう。私たちはサインイン/登録アプリケーションの開発を行います。簡単にするために、登録時にユーザー名とメールアドレスの重複をチェックします。アプリのロジックに飛ぶ前に、PHPスクリプトとMySQLデータベースを作業しましょう。まず、上記のアプリケーションの文脈で、テーブル”user”を削除し、新しいものを作成しましょう。

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)とメッセージという2つのパラメータを返します。

  • The md5() function uses the RSA Data Security, Inc. MD5 Message-Digest Algorithm to create a hash string of the password.
  • To check if the email address is a valid we’ve implemented a isValidEmail() method. FILTER_VALIDATE_EMAIL works on PHP versions 5.2.0+

アンドロイドのログイン登録プロジェクトの構造

このプロジェクトでは、アプリケーション内でHTTP呼び出しを実装するために3つのライブラリを使用しました。JSONParserクラスは、POSTおよびGETのHTTP呼び出しをlocalhostに対して実行し、そのレスポンスをJSONObjectの形式で返します。

アンドロイドのログイン登録コード

以下に、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.scdev.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();
            }


        }

    }
}

なかなか大きなコードですね!上記のコードから重要な推論を引き出しましょう。

    1. https://10.0.3.2は、localhostのリダイレクトアドレスです。このアドレスは、Genymotionエミュレータを使用している場合にのみ機能します。AVDエミュレータでは、改善されたhttps://10.0.2.2を使用してください。自分のデバイスでアプリケーションを実行している場合は、コンピュータのWIFIアドレスを代わりに使用してください。例:https://192.168.0.143。

 

    1. REGISTERボタンがクリックされると、SIGN INボタンをプログラム的に非表示にし、代わりにメールアドレスの入力テキストフィールドを表示します。

 

    1. AttemptLoginクラスは、バックグラウンドでローカルホストへのネットワークHTTPリクエストを実行します。ユーザー名、パスワード、およびメールアドレスのパラメータは、ArrayListに追加され、JSONParserクラスのmakeHttpRequest(URL, “POST”, params);メソッドに渡されます。

 

    onPostExecuteメソッドでは、サーバーから返されたメッセージ文字列をToastメッセージで表示します。

以下にJSONParser.javaクラスが示されています。

package com.scdev.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関数に渡される第2引数に応じて、HTTPPostまたはHTTPGetの対応するクラスを呼び出しています。

jObj.put("error_code",error);

上記では、最終的にMainActivityクラスに返されるJSONObjectにサーバーから返されたレスポンスステータスコードを追加しています。 注意:AndroidManifest.xmlファイルに以下の権限を追加するのを忘れないでください。

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

多くのユーザーが、このチュートリアルの最下部にコメントを投稿し、”データの取得に失敗しました”というトーストメッセージが表示されると述べています。Android 6.0以降では、Manifest.xmlファイルのapplicationタグに次の属性を追加する必要があります:android:usesCleartextTraffic=”true” なぜそうする必要があるのでしょうか?それはエミュレーター/デバイスのネットワークセキュリティがHTTP通信をするためです。以下の最新のAndroid Qエミュレーターからのスクリーンキャプチャで出力を確認してください。変更されたAndroidManifest.xmlファイルを持つ最新のソースコードはリンクとGitHubリポジトリに更新されています。

アプリケーションの動作結果は、以下に示します。

アンドロイドのユーザー登録

以下のスクリーンショットでは、新しいユーザーを登録し、それがデータベースに追加されます。登録時に入力した認証情報を使用してログインします。

Android Login With Php Mysql Final Output

下記のリンクからプロジェクトをダウンロードできます。そのプロジェクトには、PHPファイルを保持するtest_androidフォルダも含まれています。それをxampp->htdocsフォルダにコピーしてください!幸運を祈ります。

アンドロイドのログイン登録プロジェクトをPHPとMySQLでダウンロードしてください。

私たちのGithubリポジトリからも、ソースコード全体にアクセスすることもできます。

Githubのプロジェクトリンク

コメントを残す 0

Your email address will not be published. Required fields are marked *