In this tutorials, you will learn how to develop a complete Android Login Registration System with PHP, MySQL, and SQLite Databases.
Complete features in our Login System:
*Login, Registration, Reset Password, Change Password.
*Email Notification for Registration
*Password Reset through Email.
*PHP API to handle the JSON Login requests.
*MySQL database to store the user data.
*SQLite database to store Login data. In other words similar to the cookie in web browsers.
API (Application Programming Interface)
To interact with MySQL database we need to build a REST API first. REST API job is to get the request from the client, interact with the database and finally give the response back to the client. So we’ll create a simple PHP, MySQL API first. Our API do’s below jobs. ⇒ Accepts requests in GET/POST methods ⇒ Interact with the database by inserting/fetching data. ⇒ Finally will give response back in JSON format
1. Downloading & Installing WAMP
Download & Install WAMP server from www.wampserver.com/en/. Once installed, launch the program from Start ⇒ All Programs ⇒ WampServer ⇒ StartWampServer. If you are on Mac, alternatively you can use MAMP for the same. You can test your server by opening the address http://localhost/ in your browser. Also, you can check phpmyadmin by opening http://localhost/phpmyadmin Following is a screencast of Downloading and Installing WAMP Server.
2. Creating MySQL Database and Tables
Open phpmyadmin and execute below queries to create necessary database and table. Here we are creating only one table users to store users login information.
create database android_login /** Creating Database **/
use android_login /** Selecting Database **/
create table users(
`id` int(11) primary key auto_increment,
`unique_id` varchar(23) not null unique,
`name` varchar(50) not null,
`email` varchar(100) not null unique,
`encrypted_password` varchar(250) not null,
`otp` int(6) NOT NULL,
`verified` int(1) NOT NULL DEFAULT '0',
`created_at` datetime DEFAULT NULL
); /** Creating Users Table **/
3. Creating PHP Project
Go to the location where wamp installed and open www folder. The default installation location of wamp would be C:/wamp. Below is the final PHP project structure we are going to create in this article.
1. Go into www folder and create a folder named android_login. This will be the root directory of our project.
2. Now inside android_login, create a PHP file named config.php and add below content.
config.inc.php
<?php
$username = "root";
$password = "";
$host = "localhost";
$dbname = "android_login";
$options = array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8');
try {
$db = new PDO("mysql:host={$host};dbname={$dbname};charset=utf8", $username, $password, $options);
} catch(PDOException $ex) {
die("Failed to connect to the database: " . $ex->getMessage());
}
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
if(function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc()) {
function undo_magic_quotes_gpc(&$array) {
foreach($array as &$value) {
if(is_array($value)) {
undo_magic_quotes_gpc($value);
}
else {
$value = stripslashes($value);
}
}
}
undo_magic_quotes_gpc($_POST);
undo_magic_quotes_gpc($_GET);
undo_magic_quotes_gpc($_COOKIE);
}
header('Content-Type: text/html; charset=utf-8');
session_start();
?>
3.1 Registration Endpoint
Now we have all the required classes ready. Let’s start creating the endpoint for user registration. This endpoint accepts name, email, and password as POST parameters and stores the user in MySQL database. In android_login root directory, create register.php with below code.
register.php
<?php
require("config.php");
if (!empty($_POST)) {
$response = array(
"error" => FALSE
);
$query = " SELECT 1 FROM users WHERE email = :email";
//now lets update what :user should be
$query_params = array(
':email' => $_POST['email']
);
try {
$stmt = $db->prepare($query);
$result = $stmt->execute($query_params);
}
catch (PDOException $ex) {
$response["error"] = TRUE;
$response["message"] = "Database Error1. Please Try Again!";
die(json_encode($response));
}
$row = $stmt->fetch();
if ($row) {
$response["error"] = TRUE;
$response["message"] = "I'm sorry, this email is already in use";
die(json_encode($response));
} else {
$query = "INSERT INTO users ( unique_id, name, email, encrypted_password, otp, created_at ) VALUES ( :uuid, :name, :email, :encrypted_password, :otp, NOW() )";
$otp = rand(100000, 999999);
$verified = 0;
$query_params = array(
':uuid' => uniqid('', true),
':name' => $_POST['name'],
':email' => $_POST['email'],
':encrypted_password' => password_hash($_POST['password'], PASSWORD_DEFAULT),
':otp' => $otp
);
try {
$stmt = $db->prepare($query);
$result = $stmt->execute($query_params);
}
catch (PDOException $ex) {
$response["error"] = TRUE;
$response["message"] = "Database Error2. Please Try Again!";
die(json_encode($response));
}
$name = $_POST['name'];
$email = $_POST['email'];
$subject = "Android Learning Email Verification";
$message = "Hello $name,\n\nVerify that you own $email.\n\nYou may be asked to enter this confirmation code:\n\n$otp\n\nRegards,\nAndroid Learning.";
$from = "[email protected]";
$headers = "From:" . $from;
mail($email,$subject,$message,$headers);
$response["error"] = FALSE;
$response["message"] = "Register successful!";
echo json_encode($response);
}
} else {
echo 'Android Learning';
}
3.2 Email Reset
Create a PHP file named reset-password.php with below code.
reset-password.php
<?php
require("config.php");
if (isset($_POST['tag']) && $_POST['tag'] != '') {
$tag = $_POST['tag'];
$response = array("tag" => $tag, "error" => FALSE);
$query = "SELECT * FROM users WHERE email = :email";
$query_params = array(
':email' => $_POST['email']
);
try {
$stmt = $db->prepare($query);
$result = $stmt->execute($query_params);
}
catch (PDOException $ex) {
$response["error"] = true;
$response["message"] = "Database Error1. Please Try Again!";
die(json_encode($response));
}
$success = false;
$row = $stmt->fetch();
$email = $_POST['email'];
// Forgot Password
if ($tag == 'forgot_pass') {
$pass = substr(str_shuffle("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), 0, 6); // Generate new password
$newPassword = password_hash($pass, PASSWORD_DEFAULT); // Encrypted Password
if ($row) {
$stmt = $db->prepare("UPDATE users SET encrypted_password = :newPass WHERE email = :email");
$stmt->bindparam(":newPass", $newPassword);
$stmt->bindparam(":email",$email);
$stmt->execute();
$success = true;
}
if ($success == true) {
$name = $row['name'];
$subject = "New Password Request";
$message = "Hello $name.\n\nWe received a request to change your password on Android Learning\n\nYour new password:\n\n $pass\n\nRegards,\nAndroid Learning.";
$from = "[email protected]";
$headers = "From:" . $from;
mail($email,$subject,$message,$headers);
$response["error"] = false;
$response["message"] = "A new password has been sent to your e-mail address.";
die(json_encode($response));
} else {
$response["error"] = true;
$response["message"] = "Invalid Credentials!";
die(json_encode($response));
}
}
// Change Password
else if ($tag == 'change_pass') {
$oldPassword = $_POST['old_password'];
$newPassword = password_hash($_POST['password'], PASSWORD_DEFAULT);
if ($row) {
if (password_verify($oldPassword, $row['encrypted_password'])) {
$stmt = $db->prepare("UPDATE users SET encrypted_password = :password WHERE email = :email");
$stmt->bindparam(":password", $newPassword);
$stmt->bindparam(":email",$email);
$stmt->execute();
$success = true;
}
}
if ($success == true) {
$response["error"] = false;
$response["message"] = "Your Password has been changed!.";
die(json_encode($response));
} else {
$response["error"] = true;
$response["message"] = "Invalid Credentials!";
die(json_encode($response));
}
}
} else {
echo "Android Learning";
}
3.3 Verify Email Address
Create a PHP file named verification.php with below code.
verification.php
<?php
require("config.php");
if (isset($_POST['tag']) && $_POST['tag'] != '') {
$tag = $_POST['tag'];
$response = array("tag" => $tag, "error" => FALSE);
$query = "SELECT * FROM users WHERE email = :email";
$query_params = array(
':email' => $_POST['email']
);
try {
$stmt = $db->prepare($query);
$result = $stmt->execute($query_params);
}
catch (PDOException $ex) {
$response["error"] = true;
$response["message"] = "Database Error1. Please Try Again!";
die(json_encode($response));
}
$otp_ok = false;
$success = false;
$email = $_POST['email'];
$statusY = 1;
$row = $stmt->fetch();
// Forgot Password
if ($tag == 'verify_code') {
if ($row) {
if ($_POST['otp'] === $row['otp']) {
$otp_ok = true;
$stmt = $db->prepare("UPDATE users SET verified = :status WHERE email = :email");
$stmt->bindparam(":status", $statusY);
$stmt->bindparam(":email", $email);
$stmt->execute();
}
}
$query = "SELECT * FROM users WHERE email = :email";
$query_params = array(
':email' => $_POST['email']
);
try {
$stmt = $db->prepare($query);
$result = $stmt->execute($query_params);
}
catch (PDOException $ex) {
$response["error"] = true;
$response["message"] = "Database Error1. Please Try Again!";
die(json_encode($response));
}
$user = $stmt->fetch();
if ($otp_ok == true) {
$response["error"] = false;
$response["message"] = "Verify successful!";
$response["user"]["uid"] = $user["unique_id"];
$response["user"]["name"] = $user["name"];
$response["user"]["email"] = $user["email"];
$response["user"]["verified"] = $user["verified"];
$response["user"]["created_at"] = $user["created_at"];
die(json_encode($response));
} else {
$response["error"] = true;
$response["message"] = "Invalid Credentials!";
die(json_encode($response));
}
}
// Change Password
else if ($tag == 'resend_code') {
$otp = rand(100000, 999999);
if ($row) {
$stmt = $db->prepare("UPDATE users SET otp = :otp WHERE email = :email");
$stmt->bindparam(":otp", $otp);
$stmt->bindparam(":email",$email);
$stmt->execute();
$success = true;
}
if ($success == true) {
$name = $row['name'];
$email = $_POST['email'];
$subject = "Android Learning Email Verification";
$message = "Hello $name,\n\nVerify that you own $email.\n\nYou may be asked to enter this confirmation code:\n\n$otp\n\nRegards,\nAndroid Learning.";
$from = "[email protected]";
$headers = "From:" . $from;
mail($email,$subject,$message,$headers);
$response["error"] = false;
$response["message"] = "New otp has been sent to your e-mail address.";
die(json_encode($response));
}
}
} else {
echo 'Android Learning';
}
4. Create Android Project
1. In Android Studio, create a new project from File ⇒ New Project and fill all the required details.
more details go to Create New Android Project.
2. Open build.gradle and add volley library support under dependencies.
build.gradle
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'com.google.android.material:material:1.0.0'
implementation 'com.android.volley:volley:1.1.0'
}
3. Under helper package, create a class named Functions.java and add below code. In this class we declare the login, registration, email verifies and reset password URLs. While testing you need to replace the IP address with your localhost PC IP.
Functions.java
public class Functions {
//Main URL
private static String MAIN_URL = "http://192.168.225.46/android_login/";
// Login URL
public static String LOGIN_URL = MAIN_URL + "login.php";
// Register URL
public static String REGISTER_URL = MAIN_URL + "register.php";
// OTP Verification
public static String OTP_VERIFY_URL = MAIN_URL + "verification.php";
// Forgot Password
public static String RESET_PASS_URL = MAIN_URL + "reset-password.php";
......
4. Create a class named MyApplication.java. This class extends from Application which should be executed on app launch. In this class, we initiate all the volley core objects.
MyApplication.java
package org.snowcorp.login;
import android.app.Application;
import android.text.TextUtils;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.toolbox.Volley;
/**
* Created by Akshay Raj on 6/16/2016.
* [email protected]
* www.snowcorp.org
*/
public class MyApplication extends Application {
public static final String TAG = MyApplication.class.getSimpleName();
private RequestQueue mRequestQueue;
private static MyApplication mInstance;
@Override
public void onCreate() {
super.onCreate();
mInstance = this;
}
public static synchronized MyApplication getInstance() {
return mInstance;
}
public RequestQueue getRequestQueue() {
if (mRequestQueue == null) {
mRequestQueue = Volley.newRequestQueue(getApplicationContext());
}
return mRequestQueue;
}
public void addToRequestQueue(Request req, String tag) {
req.setTag(TextUtils.isEmpty(tag) ? TAG : tag);
getRequestQueue().add(req);
}
public void addToRequestQueue(Request req) {
req.setTag(TAG);
getRequestQueue().add(req);
}
public void cancelPendingRequests(Object tag) {
if (mRequestQueue != null) {
mRequestQueue.cancelAll(tag);
}
}
}
5. Under helper package, create a class named SessionManager.java and add below code. This class maintains session data across the app using the SharedPreferences. We store a boolean flag isLoggedIn in shared preferences to check the login status.
SessionManager.java
package org.snowcorp.login.helper;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.util.Log;
public class SessionManager {
// LogCat tag
private static String TAG = SessionManager.class.getSimpleName();
// Shared Preferences
SharedPreferences pref;
Editor editor;
Context _context;
// Shared pref mode
int PRIVATE_MODE = 0;
// Shared preferences file name
private static final String PREF_NAME = "AndroidLogin";
private static final String KEY_IS_LOGGEDIN = "isLoggedIn";
public SessionManager(Context context) {
this._context = context;
pref = _context.getSharedPreferences(PREF_NAME, PRIVATE_MODE);
editor = pref.edit();
}
public void setLogin(boolean isLoggedIn) {
editor.putBoolean(KEY_IS_LOGGEDIN, isLoggedIn);
// commit changes
editor.commit();
Log.d(TAG, "User login session modified!");
}
public boolean isLoggedIn(){
return pref.getBoolean(KEY_IS_LOGGEDIN, false);
}
}
6. Under helper package, create a class named DatabaseHandler.java and paste the below code. This class takes care of storing the user data in SQLite database. Whenever we need to get the logged in user information, we fetch from SQLite instead of making a request to the server.
DatabaseHandler.java
package org.snowcorp.login.helper;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import java.util.HashMap;
/**
* Created by Akshay Raj on 13-03-2016.
* Snow Corporation Inc.
* www.snowcorp.org
*/
public class DatabaseHandler extends SQLiteOpenHelper {
// All Static variables
// Database Version
private static final int DATABASE_VERSION = 1;
// Database Name
private static final String DATABASE_NAME = "AndroidLogin";
// Login table name
private static final String TABLE_LOGIN = "login";
// Login Table Columns names
private static final String KEY_ID = "id";
private static final String KEY_UID = "uid";
private static final String KEY_NAME = "name";
private static final String KEY_EMAIL = "email";
private static final String KEY_CREATED_AT = "created_at";
public DatabaseHandler(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
// Table Create Statements
private static final String CREATE_LOGIN_TABLE = "CREATE TABLE " + TABLE_LOGIN + "("
+ KEY_ID + " INTEGER PRIMARY KEY,"
+ KEY_UID + " TEXT,"
+ KEY_NAME + " TEXT,"
+ KEY_EMAIL + " TEXT UNIQUE,"
+ KEY_CREATED_AT + " TEXT" + ")";
// Creating Tables
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_LOGIN_TABLE);
}
// Upgrading database
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// Drop older table if existed
db.execSQL("DROP TABLE IF EXISTS " + TABLE_LOGIN);
// Create tables again
onCreate(db);
}
/**
* Storing user details in database
* */
public void addUser(String uid, String name, String email, String created_at) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(KEY_UID, uid); // uid
values.put(KEY_NAME, name); // FirstName
values.put(KEY_EMAIL, email); // Email
values.put(KEY_CREATED_AT, created_at); // Created At
// Inserting Row
db.insert(TABLE_LOGIN, null, values);
db.close(); // Closing database connection
}
/**
* Getting user data from database
* */
public HashMap<String, String> getUserDetails(){
HashMap<String,String> user = new HashMap<>();
String selectQuery = "SELECT * FROM " + TABLE_LOGIN;
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
// Move to first row
cursor.moveToFirst();
if(cursor.getCount() > 0){
user.put("uid", cursor.getString(1));
user.put("name", cursor.getString(2));
user.put("email", cursor.getString(3));
user.put("created_at", cursor.getString(4));
}
cursor.close();
db.close();
// return user
return user;
}
/**
* Re crate database
* Delete all tables and create them again
* */
public void resetTables(){
SQLiteDatabase db = this.getWritableDatabase();
// Delete All Rows
db.delete(TABLE_LOGIN, null, null);
db.close();
}
}
4.1 Reset Password Screen
7. Create an XML layout named reset_password.xml under res ⇒ layout.
reset_password.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="10dp">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/editEmail"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp" >
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/hint_email"
android:inputType="textEmailAddress"
android:padding="20dp"/>
</com.google.android.material.textfield.TextInputLayout>
</LinearLayout>
4.2 Adding the Login Screen
My previous article Android Login and Registration with PHP & MySQL gives you a good and simple overview of Login and Registration System.
8. Create an XML file named activity_login.xml under res ⇒ layout.
activity_login.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"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="10dp"
android:gravity="center">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/lTextEmail"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp" >
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/lEditEmail"
android:hint="@string/hint_email"
android:inputType="textEmailAddress"
android:padding="20dp"/>
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/lTextPassword"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp" >
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/lEditPassword"
android:hint="@string/hint_password"
android:inputType="textPassword"
android:padding="20dp"/>
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.button.MaterialButton
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/login"
android:layout_marginTop="20dp"
app:backgroundTint="@color/colorPrimary"
android:textColor="@color/white"
android:id="@+id/btnLogin"/>
<com.google.android.material.button.MaterialButton
style="@style/Widget.MaterialComponents.Button.TextButton"
android:id="@+id/btnLinkToRegisterScreen"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="40dip"
android:text="Register"
android:textAllCaps="false"
android:textColor="@color/colorPrimary"
android:textSize="13sp" />
<com.google.android.material.button.MaterialButton
style="@style/Widget.MaterialComponents.Button.TextButton"
android:id="@+id/btnForgotPassword"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:text="Forgot Password"
android:textAllCaps="false"
android:textColor="@color/colorPrimary"
android:textSize="13sp" />
</LinearLayout>
9. Create an activity class named LoginActivity.java.
LoginActivity.java package org.snowcorp.login; import android.app.ProgressDialog; import android.content.DialogInterface; import android.content.Intent; import android.os.Bundle; import android.text.Editable; import android.text.TextWatcher; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.WindowManager; import android.widget.Button; import android.widget.Toast; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; import com.android.volley.AuthFailureError; import com.android.volley.DefaultRetryPolicy; import com.android.volley.Request; import com.android.volley.Response; import com.android.volley.VolleyError; import com.android.volley.toolbox.StringRequest; import com.google.android.material.button.MaterialButton; import com.google.android.material.textfield.TextInputLayout; import org.json.JSONException; import org.json.JSONObject; import org.snowcorp.login.helper.DatabaseHandler; import org.snowcorp.login.helper.Functions; import org.snowcorp.login.helper.SessionManager; import java.util.HashMap; import java.util.Map; /** * Created by Akshay Raj on 6/16/2016. * [email protected] * www.snowcorp.org */ public class LoginActivity extends AppCompatActivity { private static final String TAG = LoginActivity.class.getSimpleName(); private static String KEY_UID = "uid"; private static String KEY_NAME = "name"; private static String KEY_EMAIL = "email"; private static String KEY_CREATED_AT = "created_at"; private MaterialButton btnLogin, btnLinkToRegister, btnForgotPass; private TextInputLayout inputEmail, inputPassword; private ProgressDialog pDialog; private SessionManager session; private DatabaseHandler db; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_login); inputEmail = findViewById(R.id.lTextEmail); inputPassword = findViewById(R.id.lTextPassword); btnLogin = findViewById(R.id.btnLogin); btnLinkToRegister = findViewById(R.id.btnLinkToRegisterScreen); btnForgotPass = findViewById(R.id.btnForgotPassword); // Progress dialog pDialog = new ProgressDialog(this); pDialog.setCancelable(false); // create sqlite database db = new DatabaseHandler(getApplicationContext()); // session manager session = new SessionManager(getApplicationContext()); // check user is already logged in if (session.isLoggedIn()) { Intent i = new Intent(LoginActivity.this, HomeActivity.class); startActivity(i); finish(); } // Hide Keyboard getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN); init(); } private void init() { // Login button Click Event btnLogin.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { // Hide Keyboard Functions.hideSoftKeyboard(LoginActivity.this); String email = inputEmail.getEditText().getText().toString().trim(); String password = inputPassword.getEditText().getText().toString().trim(); // Check for empty data in the form if (!email.isEmpty() && !password.isEmpty()) { if (Functions.isValidEmailAddress(email)) { // login user loginProcess(email, password); } else { Toast.makeText(getApplicationContext(), "Email is not valid!", Toast.LENGTH_SHORT).show(); } } else { // Prompt user to enter credentials Toast.makeText(getApplicationContext(), "Please enter the credentials!", Toast.LENGTH_LONG).show(); } } }); // Link to Register Screen btnLinkToRegister.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { Intent i = new Intent(LoginActivity.this, RegisterActivity.class); startActivity(i); } }); // Forgot Password Dialog btnForgotPass.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { forgotPasswordDialog(); } }); } private void forgotPasswordDialog() { final AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this); LayoutInflater inflater = getLayoutInflater(); View dialogView = inflater.inflate(R.layout.reset_password, null); dialogBuilder.setView(dialogView); dialogBuilder.setTitle("Forgot Password"); dialogBuilder.setCancelable(false); final TextInputLayout mEditEmail = dialogView.findViewById(R.id.editEmail); dialogBuilder.setPositiveButton("Reset", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { // empty } }); dialogBuilder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }); final AlertDialog alertDialog = dialogBuilder.create(); mEditEmail.getEditText().addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { if(mEditEmail.getEditText().getText().length() > 0){ alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(true); } else { alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false); } } @Override public void afterTextChanged(Editable s) { } }); alertDialog.setOnShowListener(new DialogInterface.OnShowListener() { @Override public void onShow(final DialogInterface dialog) { final Button b = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE); b.setEnabled(false); b.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { String email = mEditEmail.getEditText().getText().toString(); if (!email.isEmpty()) { if (Functions.isValidEmailAddress(email)) { resetPassword(email); dialog.dismiss(); } else { Toast.makeText(getApplicationContext(), "Email is not valid!", Toast.LENGTH_SHORT).show(); } } else { Toast.makeText(getApplicationContext(), "Fill all values!", Toast.LENGTH_SHORT).show(); } } }); } }); alertDialog.show(); } private void loginProcess(final String email, final String password) { // Tag used to cancel the request String tag_string_req = "req_login"; pDialog.setMessage("Logging in ..."); showDialog(); StringRequest strReq = new StringRequest(Request.Method.POST, Functions.LOGIN_URL, new Response.Listener() { @Override public void onResponse(String response) { Log.d(TAG, "Login Response: " + response); hideDialog(); try { JSONObject jObj = new JSONObject(response); boolean error = jObj.getBoolean("error"); // Check for error node in json if (!error) { // user successfully logged in JSONObject json_user = jObj.getJSONObject("user"); Functions logout = new Functions(); logout.logoutUser(getApplicationContext()); if(Integer.parseInt(json_user.getString("verified")) == 1){ db.addUser(json_user.getString(KEY_UID), json_user.getString(KEY_NAME), json_user.getString(KEY_EMAIL), json_user.getString(KEY_CREATED_AT)); Intent upanel = new Intent(LoginActivity.this, HomeActivity.class); upanel.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); startActivity(upanel); session.setLogin(true); finish(); } else { Bundle b = new Bundle(); b.putString("email", email); Intent upanel = new Intent(LoginActivity.this, EmailVerify.class); upanel.putExtras(b); upanel.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); startActivity(upanel); finish(); } } else { // Error in login. Get the error message String errorMsg = jObj.getString("message"); Toast.makeText(getApplicationContext(), errorMsg, Toast.LENGTH_LONG).show(); } } catch (JSONException e) { // JSON error e.printStackTrace(); Toast.makeText(getApplicationContext(), "Json error: " + e.getMessage(), Toast.LENGTH_LONG).show(); } } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { Log.e(TAG, "Login Error: " + error.getMessage()); Toast.makeText(getApplicationContext(), error.getMessage(), Toast.LENGTH_LONG).show(); hideDialog(); } }) { @Override protected Map getParams() { // Posting parameters to login url Map params = new HashMap (); params.put("email", email); params.put("password", password); return params; } }; // Adding request to request queue MyApplication.getInstance().addToRequestQueue(strReq, tag_string_req); } private void resetPassword(final String email) { // Tag used to cancel the request String tag_string_req = "req_reset_pass"; pDialog.setMessage("Please wait..."); showDialog(); StringRequest strReq = new StringRequest(Request.Method.POST, Functions.RESET_PASS_URL, new Response.Listener () { @Override public void onResponse(String response) { Log.d(TAG, "Reset Password Response: " + response); hideDialog(); try { JSONObject jObj = new JSONObject(response); boolean error = jObj.getBoolean("error"); if (!error) { Toast.makeText(getApplicationContext(), jObj.getString("message"), Toast.LENGTH_LONG).show(); } else { Toast.makeText(getApplicationContext(), jObj.getString("message"), Toast.LENGTH_LONG).show(); } } catch (JSONException e) { // JSON error e.printStackTrace(); Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_LONG).show(); } } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { Log.e(TAG, "Reset Password Error: " + error.getMessage()); Toast.makeText(getApplicationContext(), error.getMessage(), Toast.LENGTH_LONG).show(); hideDialog(); } }) { @Override protected Map getParams() { // Posting parameters to login url Map params = new HashMap<>(); params.put("tag", "forgot_pass"); params.put("email", email); return params; } @Override public Map getHeaders() throws AuthFailureError { Map params = new HashMap<>(); params.put("Content-Type", "application/x-www-form-urlencoded"); return params; } }; // Adding request to volley request queue strReq.setRetryPolicy(new DefaultRetryPolicy(5 * DefaultRetryPolicy.DEFAULT_TIMEOUT_MS, 0, 0)); strReq.setRetryPolicy(new DefaultRetryPolicy(0, 0, 0)); MyApplication.getInstance().addToRequestQueue(strReq, tag_string_req); } private void showDialog() { if (!pDialog.isShowing()) pDialog.show(); } private void hideDialog() { if (pDialog.isShowing()) pDialog.dismiss(); } }
4.3 Adding the Email Verify Screen
10. Create an XML layout named activity_email_verify.xml under res ⇒ layout.
activity_email_verify.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"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="16dp">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/verify_code"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="30dp">
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="20dp"
android:hint="Verification Code"
android:inputType="number"
android:maxLength="6" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.button.MaterialButton
android:id="@+id/btnVerify"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:backgroundTint="@color/colorPrimary"
android:textColor="@color/white"
android:text="Verify"/>
<com.google.android.material.button.MaterialButton
style="@style/Widget.MaterialComponents.Button.TextButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:textColor="@color/borderless_button"
android:text="Resend Code"
android:id="@+id/btnResendCode" />
<TextView
android:id="@+id/otpCountDown"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:gravity="center"/>
</LinearLayout>
11. Create an activity class named EmailVerify.java db.addUser() – Will insert the user in SQLite database once he is successfully verified his Email.
EmailVerify.java package org.snowcorp.login; import android.annotation.SuppressLint; import android.app.ProgressDialog; import android.content.Intent; import android.os.Bundle; import android.os.CountDownTimer; import android.util.Log; import android.view.View; import android.view.WindowManager; import android.widget.TextView; import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; import com.android.volley.AuthFailureError; import com.android.volley.Request; import com.android.volley.Response; import com.android.volley.VolleyError; import com.android.volley.toolbox.StringRequest; import com.google.android.material.button.MaterialButton; import com.google.android.material.textfield.TextInputLayout; import org.json.JSONException; import org.json.JSONObject; import org.snowcorp.login.helper.DatabaseHandler; import org.snowcorp.login.helper.Functions; import org.snowcorp.login.helper.SessionManager; import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit; /** * Created by Akshay Raj on 06-02-2017. * [email protected] * www.snowcorp.org */ public class EmailVerify extends AppCompatActivity { private static final String TAG = EmailVerify.class.getSimpleName(); private TextInputLayout textVerifyCode; private MaterialButton btnVerify, btnResend; private TextView otpCountDown; private SessionManager session; private DatabaseHandler db; private ProgressDialog pDialog; private static final String FORMAT = "%02d:%02d"; Bundle bundle; private static String KEY_UID = "uid"; private static String KEY_NAME = "name"; private static String KEY_EMAIL = "email"; private static String KEY_CREATED_AT = "created_at"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_email_verify); textVerifyCode = findViewById(R.id.verify_code); btnVerify = findViewById(R.id.btnVerify); btnResend = findViewById(R.id.btnResendCode); otpCountDown = findViewById(R.id.otpCountDown); bundle = getIntent().getExtras(); db = new DatabaseHandler(getApplicationContext()); session = new SessionManager(getApplicationContext()); pDialog = new ProgressDialog(this); pDialog.setCancelable(false); // Hide Keyboard getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN); init(); } private void init() { btnVerify.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // Hide Keyboard Functions.hideSoftKeyboard(EmailVerify.this); String email = bundle.getString("email"); String otp = textVerifyCode.getEditText().getText().toString(); if (!otp.isEmpty()) { verifyCode(email, otp); textVerifyCode.setErrorEnabled(false); } else { textVerifyCode.setError("Please enter verification code"); } } }); btnResend.setEnabled(false); btnResend.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String email = bundle.getString("email"); resendCode(email); } }); countDown(); } private void countDown() { new CountDownTimer(70000, 1000) { // adjust the milli seconds here @SuppressLint({"SetTextI18n", "DefaultLocale"}) public void onTick(long millisUntilFinished) { otpCountDown.setVisibility(View.VISIBLE); otpCountDown.setText(""+String.format(FORMAT, TimeUnit.MILLISECONDS.toMinutes(millisUntilFinished), TimeUnit.MILLISECONDS.toSeconds(millisUntilFinished) - TimeUnit.MINUTES.toSeconds( TimeUnit.MILLISECONDS.toMinutes(millisUntilFinished)) )); } public void onFinish() { otpCountDown.setVisibility(View.GONE); btnResend.setEnabled(true); } }.start(); } private void verifyCode(final String email, final String otp) { // Tag used to cancel the request String tag_string_req = "req_verify_code"; pDialog.setMessage("Checking in ..."); showDialog(); StringRequest strReq = new StringRequest(Request.Method.POST, Functions.OTP_VERIFY_URL, new Response.Listener() { @Override public void onResponse(String response) { Log.d(TAG, "Verification Response: " + response); hideDialog(); try { JSONObject jObj = new JSONObject(response); boolean error = jObj.getBoolean("error"); // Check for error node in json if (!error) { JSONObject json_user = jObj.getJSONObject("user"); Functions logout = new Functions(); logout.logoutUser(getApplicationContext()); db.addUser(json_user.getString(KEY_UID), json_user.getString(KEY_NAME), json_user.getString(KEY_EMAIL), json_user.getString(KEY_CREATED_AT)); session.setLogin(true); Intent upanel = new Intent(EmailVerify.this, HomeActivity.class); upanel.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); startActivity(upanel); finish(); } else { Toast.makeText(getApplicationContext(), "Invalid Verification Code", Toast.LENGTH_LONG).show(); textVerifyCode.setError("Invalid Verification Code"); } } catch (JSONException e) { // JSON error e.printStackTrace(); Toast.makeText(getApplicationContext(), "Json error: " + e.getMessage(), Toast.LENGTH_LONG).show(); } } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { Log.e(TAG, "Verify Code Error: " + error.getMessage()); Toast.makeText(getApplicationContext(), error.getMessage(), Toast.LENGTH_LONG).show(); hideDialog(); } }) { @Override protected Map getParams() { // Posting parameters to login url Map params = new HashMap<>(); params.put("tag", "verify_code"); params.put("email", email); params.put("otp", otp); return params; } @Override public Map getHeaders() throws AuthFailureError { Map params = new HashMap (); params.put("Content-Type","application/x-www-form-urlencoded"); return params; } }; // Adding request to request queue MyApplication.getInstance().addToRequestQueue(strReq, tag_string_req); } private void resendCode(final String email) { // Tag used to cancel the request String tag_string_req = "req_resend_code"; pDialog.setMessage("Resending code ..."); showDialog(); StringRequest strReq = new StringRequest(Request.Method.POST, Functions.OTP_VERIFY_URL, new Response.Listener () { @Override public void onResponse(String response) { Log.d(TAG, "Resend Code Response: " + response); hideDialog(); try { JSONObject jObj = new JSONObject(response); boolean error = jObj.getBoolean("error"); // Check for error node in json if (!error) { Toast.makeText(getApplicationContext(), "Code successfully sent to your email!", Toast.LENGTH_LONG).show(); btnResend.setEnabled(false); countDown(); } else { Toast.makeText(getApplicationContext(), "Code sending failed!", Toast.LENGTH_LONG).show(); } } catch (JSONException e) { // JSON error e.printStackTrace(); Toast.makeText(getApplicationContext(), "Json error: " + e.getMessage(), Toast.LENGTH_LONG).show(); } } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { Log.e(TAG, "Resend Code Error: " + error.getMessage()); Toast.makeText(getApplicationContext(), error.getMessage(), Toast.LENGTH_LONG).show(); hideDialog(); } }) { @Override protected Map getParams() { // Posting parameters to login url Map params = new HashMap (); params.put("tag", "resend_code"); params.put("email", email); return params; } @Override public Map getHeaders() throws AuthFailureError { Map params = new HashMap (); params.put("Content-Type","application/x-www-form-urlencoded"); return params; } }; // Adding request to request queue MyApplication.getInstance().addToRequestQueue(strReq, tag_string_req); } private void showDialog() { if (!pDialog.isShowing()) pDialog.show(); } private void hideDialog() { if (pDialog.isShowing()) pDialog.dismiss(); } @Override public void onResume(){ super.onResume(); countDown(); } }
4.4 Adding the Home Screen
Until now we are done with login, registration and email verify screen. Now we’ll add the final screen to show the logged in user information. This information will be fetched from SQLite database once user is logged in. Here are two buttons for logout for destroy current session and change password for change old password. 12. Create an xml file named activity_home.xml under res ⇒ layout and add below code.
activity_home.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_margin="20dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="top|center">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/welcome"
android:textSize="20sp" />
<TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:textSize="24sp" />
<TextView
android:id="@+id/email"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="13sp"/>
</LinearLayout>
<com.google.android.material.button.MaterialButton
android:id="@+id/change_password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@+id/logout"
android:layout_marginBottom="10dp"
app:backgroundTint="@color/colorPrimary"
android:text="@string/change_password"
android:textColor="@color/white"/>
<com.google.android.material.button.MaterialButton
android:id="@+id/logout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
app:backgroundTint="#F44336"
android:text="@string/logout"
android:textColor="@color/white"/>
</RelativeLayout>
13. Open the HomeActivity.java and do below changes. Here we are just fetching the logged user information from SQLite and displaying it on the screen. The logout button will logout the user by clearing the session and deleting the user from SQLite table and Change Password button for changing current password.
HomeActivity.java package org.snowcorp.login; import android.app.ProgressDialog; import android.content.DialogInterface; import android.content.Intent; import android.os.Bundle; import android.text.Editable; import android.text.TextWatcher; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.WindowManager; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; import com.android.volley.AuthFailureError; import com.android.volley.DefaultRetryPolicy; import com.android.volley.Request; import com.android.volley.Response; import com.android.volley.VolleyError; import com.android.volley.toolbox.StringRequest; import com.google.android.material.button.MaterialButton; import com.google.android.material.textfield.TextInputLayout; import org.json.JSONException; import org.json.JSONObject; import org.snowcorp.login.helper.DatabaseHandler; import org.snowcorp.login.helper.Functions; import org.snowcorp.login.helper.SessionManager; import java.util.HashMap; import java.util.Map; /** * Created by Akshay Raj on 6/16/2016. * [email protected] * www.snowcorp.org */ public class HomeActivity extends AppCompatActivity { private static final String TAG = HomeActivity.class.getSimpleName(); private TextView txtName, txtEmail; private MaterialButton btnChangePass, btnLogout; private SessionManager session; private DatabaseHandler db; private ProgressDialog pDialog; private HashMapuser = new HashMap<>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_home); txtName = findViewById(R.id.name); txtEmail = findViewById(R.id.email); btnChangePass = findViewById(R.id.change_password); btnLogout = findViewById(R.id.logout); // Progress dialog pDialog = new ProgressDialog(this); pDialog.setCancelable(false); db = new DatabaseHandler(getApplicationContext()); user = db.getUserDetails(); // session manager session = new SessionManager(getApplicationContext()); if (!session.isLoggedIn()) { logoutUser(); } // Fetching user details from database String name = user.get("name"); String email = user.get("email"); // Displaying the user details on the screen txtName.setText(name); txtEmail.setText(email); // Hide Keyboard getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN); init(); } private void init() { btnLogout.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { logoutUser(); } }); btnChangePass.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { final AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(HomeActivity.this); LayoutInflater inflater = getLayoutInflater(); View dialogView = inflater.inflate(R.layout.change_password, null); dialogBuilder.setView(dialogView); dialogBuilder.setTitle("Change Password"); dialogBuilder.setCancelable(false); final TextInputLayout oldPassword = dialogView.findViewById(R.id.old_password); final TextInputLayout newPassword = dialogView.findViewById(R.id.new_password); dialogBuilder.setPositiveButton("Change", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { // empty } }); dialogBuilder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }); final AlertDialog alertDialog = dialogBuilder.create(); TextWatcher textWatcher = new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { if(oldPassword.getEditText().getText().length() > 0 && newPassword.getEditText().getText().length() > 0){ alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(true); } else { alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false); } } @Override public void afterTextChanged(Editable s) { } }; oldPassword.getEditText().addTextChangedListener(textWatcher); newPassword.getEditText().addTextChangedListener(textWatcher); alertDialog.setOnShowListener(new DialogInterface.OnShowListener() { @Override public void onShow(final DialogInterface dialog) { final Button b = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE); b.setEnabled(false); b.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { String email = user.get("email"); String old_pass = oldPassword.getEditText().getText().toString(); String new_pass = newPassword.getEditText().getText().toString(); if (!old_pass.isEmpty() && !new_pass.isEmpty()) { changePassword(email, old_pass, new_pass); dialog.dismiss(); } else { Toast.makeText(getApplicationContext(), "Fill all values!", Toast.LENGTH_SHORT).show(); } } }); } }); alertDialog.show(); } }); } private void logoutUser() { session.setLogin(false); // Launching the login activity Functions logout = new Functions(); logout.logoutUser(getApplicationContext()); Intent intent = new Intent(HomeActivity.this, LoginActivity.class); startActivity(intent); finish(); } private void changePassword(final String email, final String old_pass, final String new_pass) { // Tag used to cancel the request String tag_string_req = "req_reset_pass"; pDialog.setMessage("Please wait..."); showDialog(); StringRequest strReq = new StringRequest(Request.Method.POST, Functions.RESET_PASS_URL, new Response.Listener () { @Override public void onResponse(String response) { Log.d(TAG, "Reset Password Response: " + response); hideDialog(); try { JSONObject jObj = new JSONObject(response); boolean error = jObj.getBoolean("error"); if (!error) { Toast.makeText(getApplicationContext(), jObj.getString("message"), Toast.LENGTH_LONG).show(); } else { Toast.makeText(getApplicationContext(), jObj.getString("message"), Toast.LENGTH_LONG).show(); } } catch (JSONException e) { // JSON error e.printStackTrace(); Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_LONG).show(); } } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { Log.e(TAG, "Reset Password Error: " + error.getMessage()); Toast.makeText(getApplicationContext(), error.getMessage(), Toast.LENGTH_LONG).show(); hideDialog(); } }) { @Override protected Map getParams() { // Posting parameters to login url Map params = new HashMap<>(); params.put("tag", "change_pass"); params.put("email", email); params.put("old_password", old_pass); params.put("password", new_pass); return params; } @Override public Map getHeaders() throws AuthFailureError { Map params = new HashMap<>(); params.put("Content-Type", "application/x-www-form-urlencoded"); return params; } }; // Adding request to volley request queue strReq.setRetryPolicy(new DefaultRetryPolicy(5 * DefaultRetryPolicy.DEFAULT_TIMEOUT_MS, 0, 0)); strReq.setRetryPolicy(new DefaultRetryPolicy(0, 0, 0)); MyApplication.getInstance().addToRequestQueue(strReq, tag_string_req); } private void showDialog() { if (!pDialog.isShowing()) pDialog.show(); } private void hideDialog() { if (pDialog.isShowing()) pDialog.dismiss(); } }
4.5 Some Important Functions
1. Email Address Validation
public static boolean isValidEmailAddress(String email) { String ePattern = "^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$"; java.util.regex.Pattern p = java.util.regex.Pattern.compile(ePattern); java.util.regex.Matcher m = p.matcher(email); return m.matches(); }
2. Hide Soft Keyboard
public static void hideSoftKeyboard(Activity activity) { InputMethodManager inputMethodManager = (InputMethodManager) activity.getSystemService( Activity.INPUT_METHOD_SERVICE); inputMethodManager.hideSoftInputFromWindow( activity.getCurrentFocus().getWindowToken(), 0); }
5. Testing the App
For a beginner it will be always difficult to run this project for the first time. But don’t worry, the following steps will helps you testing this app. (The ip address looks like 192.168.225.46) ⇒ Make sure that both devices (the device running the PHP project and the android device) are on the same wifi network. ⇒ Give correct username , password and database name of MySQL in config.php ⇒ Replace the URL ip address of MAIN_URL in AppConfig.java with your machine ip address. You can get the ip address by running ipconfig in cmd
6. Download Complete Project
You can download complete project at Github
[et_bloom_locked optin_id=optin_3]Download Project[/et_bloom_locked]
good
Thank You 🙂
hi i can’t connect to the mail server
Use real server not local server
can please give me an example of how to do that am using this for my final year project thank you.
Upload your project to any web hosting then try
OK thanks very much let me try that ,i will get back to you if i run in any error.Is that ok?
Ok..you can message me at my facebook (@akrajilwar )
great 🙂
this is the error :”Warning: mail(): Failed to connect to mailserver at "localhost" port 25, verify your "SMTP" and "smtp_port" setting in php.ini or use ini_set() in C:\xampp\htdocs\android_login\register.php on line 71
{“error”:false,”message”:”Register successful!”}”
mail() function not work in local server (wamp server). Try with real server
where can i find your login.php file? you do not mention it
Check my source code on GitHub with this link https://github.com/akrajilwar/Android-Login-And-Registration
Hey, im getting error..
“Json error: Value
send me full log
I have nothing in my email when asking verify code, whats wrong?
did you try with online server?
im using wampserver installed on my laptop and internet connected by wifi, for url i used ip address 192.168.1.2:8080 (refer to ipconfig). but when i try to RESEND CODE i got error message Json error:value
If you want to test mail function then you need online server
i mean i got error message “Json error:value “
Add two slash (//) before mail() function for testing. You can get verification code from phpmyadmin and if you want to try mail function then add your project to online server and remove slash from mail function
Thanks a lot for your assist
Where will I add that
The first user is created perfectly, but when I try to register the second user it says “Database Error2. Please Try Again!”. I removed the first user from the mysql db and it again registered the 1st user and again an error on registering the 2nd user.
Set your database to auto increase
getting null value for strReq in volley while registering
strReq=[ ] http://sritronix.in/registration_login/register.php 0x179440dd NORMAL null
I can’t see the login.php
https://github.com/akrajilwar/Android-Login-And-Registration/blob/master/server_side_php/login.php
Thank you man!
Am having an error trying to register;
java.lang.NullPointerException: Attempt to invoke virtual method ‘void com.waynem.kejaapp.MyApplication.addToRequestQueue(com.android.volley.Request, java.lang.String)’ on a null object reference
Help me
02-19 12:26:52.473 10195-10195/com.waynem.kejaapp E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.waynem.kejaapp, PID: 10195
java.lang.NullPointerException: Attempt to invoke virtual method ‘void com.waynem.kejaapp.MyApplication.addToRequestQueue(com.android.volley.Request, java.lang.String)’ on a null object reference
at com.waynem.kejaapp.RegisterActivity.registerUser(RegisterActivity.java:163)
at com.waynem.kejaapp.RegisterActivity.access$300(RegisterActivity.java:32)
at com.waynem.kejaapp.RegisterActivity$1.onClick(RegisterActivity.java:75)
at android.view.View.performClick(View.java:4848)
at android.view.View$PerformClick.run(View.java:20262)
at android.os.Handler.handleCallback(Handler.java:815)
at android.os.Handler.dispatchMessage(Handler.java:104)
at android.os.Looper.loop(Looper.java:194)
at android.app.ActivityThread.main(ActivityThread.java:5637)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:960)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
Sir i have executed the app but when i goto register activity then it goes to login activity and when i try to login then app crashes and closed. There is no data in mysql database. Please help me sir.
add MyApplication in Manifeast.xml
I have followed all the steps on the tutorial. But when I either register or login on the app it invokes the registering dialog or the login dialog but it then shows an empty dialog nothing happens there after. Please help I am already using an online server
send your android studio log to my facebook fb.me/akrajilwar
Please write the solution if some one sorted out
Hello,
I have exactly the same problem to find the solution?
Thank you
send log to my fb https://fb.me/akrajilwar
Hello sir,
In Forgot password ,when I enter email address, I am getting error [value
hello, In forgot password, mail is sent but not received. Below is the error log. Please help.
[Thu May 24 10:25:34.653603 2018] [mpm_winnt:notice] [pid 10060:tid 680] AH00364: Child: All worker threads have exited.
[Thu May 24 10:25:34.702636 2018] [mpm_winnt:notice] [pid 8924:tid 760] AH00430: Parent: Child process 10060 exited successfully.
[Thu May 24 10:25:39.813855 2018] [ssl:warn] [pid 32:tid 740] AH01909: http://www.example.com:443:0 server certificate does NOT include an ID which matches the server name
[Thu May 24 10:25:39.890192 2018] [ssl:warn] [pid 32:tid 740] AH01909: http://www.example.com:443:0 server certificate does NOT include an ID which matches the server name
[Thu May 24 10:25:39.917211 2018] [mpm_winnt:notice] [pid 32:tid 740] AH00455: Apache/2.4.33 (Win32) OpenSSL/1.1.0h PHP/7.2.5 configured — resuming normal operations
[Thu May 24 10:25:39.917211 2018] [mpm_winnt:notice] [pid 32:tid 740] AH00456: Apache Lounge VC15 Server built: Mar 28 2018 12:12:41
[Thu May 24 10:25:39.917211 2018] [core:notice] [pid 32:tid 740] AH00094: Command line: ‘C:\\xampp\\apache\\bin\\httpd.exe -d C:/xampp/apache’
[Thu May 24 10:25:39.946781 2018] [mpm_winnt:notice] [pid 32:tid 740] AH00418: Parent: Created child process 6424
[Thu May 24 10:25:40.478289 2018] [ssl:warn] [pid 6424:tid 656] AH01909: http://www.example.com:443:0 server certificate does NOT include an ID which matches the server name
[Thu May 24 10:25:40.537104 2018] [ssl:warn] [pid 6424:tid 656] AH01909: http://www.example.com:443:0 server certificate does NOT include an ID which matches the server name
[Thu May 24 10:25:40.564123 2018] [mpm_winnt:notice] [pid 6424:tid 656] AH00354: Child: Starting 150 worker threads.
sendmail: Error during delivery: Please log in via your web brows
mail() function does not work in local server. upload your website to real server then test mail()
hello Sir,
I am getting error at b.putstring(“email”,email) in login activity,and also in getString method.
It says, putstring cannot be resolved
I have made a new project and added this files. app is closing without showing any matching errors in error log.
But your project which i have downloaded is working
I got this error
W/System.err: org.json.JSONException: Value Failed of type java.lang.String cannot be converted to JSONObject
W/System.err: at org.json.JSON.typeMismatch(JSON.java:111)
W/System.err: at org.json.JSONObject.(JSONObject.java:160)
W/System.err: at org.json.JSONObject.(JSONObject.java:173)
W/System.err: at com.dugange.hilarym.androidtodatabase.RegisterActivity$3.onResponse(RegisterActivity.java:108)
W/System.err: at com.dugange.hilarym.androidtodatabase.RegisterActivity$3.onResponse(RegisterActivity.java:100)
Your help please
You are getting error in php file. Can you send me full log in text file. My email is [email protected]
I got this error
W/System.err: org.json.JSONException: Value Failed of type java.lang.String cannot be converted to JSONObject
W/System.err: at org.json.JSON.typeMismatch(JSON.java:111)
W/System.err: at org.json.JSONObject.(JSONObject.java:160)
W/System.err: at org.json.JSONObject.(JSONObject.java:173)
W/System.err: at com.dugange.hilarym.androidtodatabase.RegisterActivity$3.onResponse(RegisterActivity.java:108)
W/System.err: at com.dugange.hilarym.androidtodatabase.RegisterActivity$3.onResponse(RegisterActivity.java:100)
Your help please
great login App, thank you.
hello sir
when i click LOGIN or REGISTER a blank dark toast shows and nothing happens
have u able to fix that im also having same problem
I connected LAN with ipv4 address 192.168.137.1
so changed to
String MAIN_URL = “http://192.168.137.1/android_login/”;
I created folder android_login pasted those php files
I copied android project
I created database android_login, created table users as mentioned
Used Xampp so all inside htdocs folder
changed username and password in config.php
Getting error:
E/RegisterActivity: Registration Error: null
com.android.volley.TimeoutError
at com.android.volley.toolbox.BasicNetwork.performRequest(BasicNetwork.java:169)
at com.android.volley.NetworkDispatcher.processRequest(NetworkDispatcher.java:120)
at com.android.volley.NetworkDispatcher.run(NetworkDispatcher.java:87)
Dear Mr. Akshay Raj,
I need more information on “otp” and email verification. Could you please inform where or how can I find the above info?
Thanks and best regards.
When you’ll register then you’ll receive an email with 6 digits number. you need to provide this code to email verification activity to verify email.
getting a syntax error on SQL query
Hello,
Everything works fine except the verification code that I do not get on my email address. I am on an external server.
Thank you
did you use this on real server, not localhost? Actually, mail() function not working on localhost.
I am on an external server and the mail goes well but never arrives.
Should the [email protected] address be changed in the register.php or not?
thank you
Hello,
Everything works fine except that I never receive the verification code by email.
Can you help me
Thank you
thanks for the explanation, but I don’t know where is Helper package !?
download full source code then you can find helper package.
hi
thank you so much but where is the source code
at the end of tutorial.
Pls the password is not resseting, and not sending anything to my mail on local server.
mail() function is not working on local server
hi android they should be a way to make it work on local server by installing a library
Pls which line are you talking about the mail() function
I have another error when using forgot password
it shows error below
(value <br of type java.lang.string cannot be converted to jsonobject)
Pls how will i do this
This is the log
( ! ) Warning: mail(): Failed to connect to mailserver at "localhost" port 25, verify your "SMTP" and "smtp_port" setting in php.ini or use ini_set() in C:\wamp64\www\unilever_app\reset-password.php on line 54
Call Stack
#TimeMemoryFunctionLocation
10.0010407224{main}( )…\reset-password.php:0
20.1527460384mail
( )…\reset-password.php:54
{“tag”:”forgot_pass”,”error”:false,”message”:”A new password has been sent to your e-mail address.”,”mail”:”Hello Muibi Azeez Abolade.\n\nWe received a request to change your password on Agbara Engineering App\n\nYour new password:\n\n HgFASy\n\nRegards,\nAgbara Engineering App.”}
2020-03-19 08:20:40.173 12050-12082/org.unilever.centralengineering D/EGL_emulation: eglMakeCurrent: 0x7fa9f0637aa0: ver 3 1 (tinfo 0x7fa9f060c1a0)
2020-03-19 08:20:40.195 12050-12050/org.unilever.centralengineering W/System.err: org.json.JSONException: Value <br of type java.lang.String cannot be converted to JSONObject
2020-03-19 08:20:40.196 12050-12050/org.unilever.centralengineering W/System.err: at org.json.JSON.typeMismatch(JSON.java:111)
2020-03-19 08:20:40.196 12050-12050/org.unilever.centralengineering W/System.err: at org.json.JSONObject.(JSONObject.java:160)
2020-03-19 08:20:40.196 12050-12050/org.unilever.centralengineering W/System.err: at org.json.JSONObject.(JSONObject.java:173)
2020-03-19 08:20:40.196 12050-12050/org.unilever.centralengineering W/System.err: at org.unilever.centralengineering.LoginActivity$11.onResponse(LoginActivity.java:311)
2020-03-19 08:20:40.196 12050-12050/org.unilever.centralengineering W/System.err: at org.unilever.centralengineering.LoginActivity$11.onResponse(LoginActivity.java:303)
2020-03-19 08:20:40.196 12050-12050/org.unilever.centralengineering W/System.err: at com.android.volley.toolbox.StringRequest.deliverResponse(StringRequest.java:78)
2020-03-19 08:20:40.196 12050-12050/org.unilever.centralengineering W/System.err: at com.android.volley.toolbox.StringRequest.deliverResponse(StringRequest.java:30)
2020-03-19 08:20:40.196 12050-12050/org.unilever.centralengineering W/System.err: at com.android.volley.ExecutorDelivery$ResponseDeliveryRunnable.run(ExecutorDelivery.java:106)
2020-03-19 08:20:40.196 12050-12050/org.unilever.centralengineering W/System.err: at android.os.Handler.handleCallback(Handler.java:751)
2020-03-19 08:20:40.196 12050-12050/org.unilever.centralengineering W/System.err: at android.os.Handler.dispatchMessage(Handler.java:95)
2020-03-19 08:20:40.196 12050-12050/org.unilever.centralengineering W/System.err: at android.os.Looper.loop(Looper.java:154)
2020-03-19 08:20:40.197 12050-12050/org.unilever.centralengineering W/System.err: at android.app.ActivityThread.main(ActivityThread.java:6125)
2020-03-19 08:20:40.197 12050-12050/org.unilever.centralengineering W/System.err: at java.lang.reflect.Method.invoke(Native Method)
2020-03-19 08:20:40.197 12050-12050/org.unilever.centralengineering W/System.err: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:893)
2020-03-19 08:20:40.197 12050-12050/org.unilever.centralengineering W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:783)
2020-03-19 08:20:40.213 12050-12082/org.unilever.centralengineering D/EGL_emulation: eglMakeCurrent: 0x7fa9f0637aa0: ver 3 1 (tinfo 0x7fa9f060c1a0)
2020-03-19 08:20:40.307 12050-12082/org.unilever.centralengineering E/EGL_emulation: tid 12082: eglSurfaceAttrib(1259): error 0x3009 (EGL_BAD_MATCH)
2020-03-19 08:20:40.307 12050-12082/org.unilever.centralengineering W/OpenGLRenderer: Failed to set EGL_SWAP_BEHAVIOR on surface 0x7fa9dac41cc0, error=EGL_BAD_MATCH
2020-03-19 08:20:40.307 12050-12050/org.unilever.centralengineering W/IInputConnectionWrapper: finishComposingText on inactive InputConnection
2020-03-19 08:20:40.314 12050-12082/org.unilever.centralengineering D/EGL_emulation: eglMakeCurrent: 0x7fa9f0637aa0: ver 3 1 (tinfo 0x7fa9f060c1a0)
2020-03-19 08:20:40.711 12050-12082/org.unilever.centralengineering D/EGL_emulation: eglMakeCurrent: 0x7fa9f0637aa0: ver 3 1 (tinfo 0x7fa9f060c1a0)
yes is work. !! in my first post i tell how can you do. But i use xamp with sendmail.
This has been depreciated on CONFIG.PHP
if(function_exists(‘get_magic_quotes_gpc’) && get_magic_quotes_gpc()) {
function undo_magic_quotes_gpc(&$array) {
foreach($array as &$value) {
if(is_array($value)) {
undo_magic_quotes_gpc($value);
}
else {
$value = stripslashes($value);
}
}
}
undo_magic_quotes_gpc($_POST);
undo_magic_quotes_gpc($_GET);
undo_magic_quotes_gpc($_COOKIE);
}
This post is worth everyone’s attention. How can I find out more?
Pls which line are you talking about the mail() function
I have another error when using forgot password
it shows error below
(value <br of type java.lang.string cannot be converted to jsonobject)
Pls how will i do this
This is the log
( ! ) Warning: mail(): Failed to connect to mailserver at "localhost" port 25, verify your "SMTP" and "smtp_port" setting in php.ini or use ini_set() in C:\wamp64\www\unilever_app\reset-password.php on line 54
Call Stack
#TimeMemoryFunctionLocation
10.0010407224{main}( )…\reset-password.php:0
20.1527460384mail
( )…\reset-password.php:54
{“tag”:”forgot_pass”,”error”:false,”message”:”A new password has been sent to your e-mail address.”,”mail”:”Hello Muibi Azeez Abolade.\n\nWe received a request to change your password on Agbara Engineering App\n\nYour new password:\n\n HgFASy\n\nRegards,\nAgbara Engineering App.”}
2020-03-19 08:20:40.173 12050-12082/org.unilever.centralengineering D/EGL_emulation: eglMakeCurrent: 0x7fa9f0637aa0: ver 3 1 (tinfo 0x7fa9f060c1a0)
2020-03-19 08:20:40.195 12050-12050/org.unilever.centralengineering W/System.err: org.json.JSONException: Value <br of type java.lang.String cannot be converted to JSONObject
2020-03-19 08:20:40.196 12050-12050/org.unilever.centralengineering W/System.err: at org.json.JSON.typeMismatch(JSON.java:111)
2020-03-19 08:20:40.196 12050-12050/org.unilever.centralengineering W/System.err: at org.json.JSONObject.(JSONObject.java:160)
2020-03-19 08:20:40.196 12050-12050/org.unilever.centralengineering W/System.err: at org.json.JSONObject.(JSONObject.java:173)
2020-03-19 08:20:40.196 12050-12050/org.unilever.centralengineering W/System.err: at org.unilever.centralengineering.LoginActivity$11.onResponse(LoginActivity.java:311)
2020-03-19 08:20:40.196 12050-12050/org.unilever.centralengineering W/System.err: at org.unilever.centralengineering.LoginActivity$11.onResponse(LoginActivity.java:303)
2020-03-19 08:20:40.196 12050-12050/org.unilever.centralengineering W/System.err: at com.android.volley.toolbox.StringRequest.deliverResponse(StringRequest.java:78)
2020-03-19 08:20:40.196 12050-12050/org.unilever.centralengineering W/System.err: at com.android.volley.toolbox.StringRequest.deliverResponse(StringRequest.java:30)
2020-03-19 08:20:40.196 12050-12050/org.unilever.centralengineering W/System.err: at com.android.volley.ExecutorDelivery$ResponseDeliveryRunnable.run(ExecutorDelivery.java:106)
2020-03-19 08:20:40.196 12050-12050/org.unilever.centralengineering W/System.err: at android.os.Handler.handleCallback(Handler.java:751)
2020-03-19 08:20:40.196 12050-12050/org.unilever.centralengineering W/System.err: at android.os.Handler.dispatchMessage(Handler.java:95)
2020-03-19 08:20:40.196 12050-12050/org.unilever.centralengineering W/System.err: at android.os.Looper.loop(Looper.java:154)
2020-03-19 08:20:40.197 12050-12050/org.unilever.centralengineering W/System.err: at android.app.ActivityThread.main(ActivityThread.java:6125)
2020-03-19 08:20:40.197 12050-12050/org.unilever.centralengineering W/System.err: at java.lang.reflect.Method.invoke(Native Method)
2020-03-19 08:20:40.197 12050-12050/org.unilever.centralengineering W/System.err: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:893)
2020-03-19 08:20:40.197 12050-12050/org.unilever.centralengineering W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:783)
2020-03-19 08:20:40.213 12050-12082/org.unilever.centralengineering D/EGL_emulation: eglMakeCurrent: 0x7fa9f0637aa0: ver 3 1 (tinfo 0x7fa9f060c1a0)
2020-03-19 08:20:40.307 12050-12082/org.unilever.centralengineering E/EGL_emulation: tid 12082: eglSurfaceAttrib(1259): error 0x3009 (EGL_BAD_MATCH)
2020-03-19 08:20:40.307 12050-12082/org.unilever.centralengineering W/OpenGLRenderer: Failed to set EGL_SWAP_BEHAVIOR on surface 0x7fa9dac41cc0, error=EGL_BAD_MATCH
2020-03-19 08:20:40.307 12050-12050/org.unilever.centralengineering W/IInputConnectionWrapper: finishComposingText on inactive InputConnection
2020-03-19 08:20:40.314 12050-12082/org.unilever.centralengineering D/EGL_emulation: eglMakeCurrent: 0x7fa9f0637aa0: ver 3 1 (tinfo 0x7fa9f060c1a0)
2020-03-19 08:20:40.711 12050-12082/org.unilever.centralengineering D/EGL_emulation: eglMakeCurrent: 0x7fa9f0637aa0: ver 3 1 (tinfo 0x7fa9f060c1a0)
i am using window 32 bit with xamp,
when i run the app from my mobile and try to register no any error pop up simly try to serch for some tme and quit
check ip address
I set my IP address to 192.168.1.2. and make change to code accordingly.
Is there any special configuration on xamp side needed.
How can I send you screenshoot
when i try to register or login from mobile after searching a little bit show me pop at bottom of interface below forgot password something like big dot.
i am in the same wifi with local server,
i can acess the server from browser through URL ‘ http://192.168.1.2/dashboard/‘
this url work in mobile device?
yes from i can acces from mobile browser
send log monitor screenshot to our fb page
two error log as below,
am using Xampp Apache 2.4.29,on window 10 win 32 bit, i tried to adjust different configuration, stop window defender firewall, reinstall Xampp but still no solution.
[Sat Apr 18 15:55:46.275274 2020] [authz_core:error] [pid 5900:tid 1896] [client 192.168.1.3:53858] AH01630: client denied by server configuration: C:/xampp/htdocs/~snow
[Sat Apr 18 15:55:46.319409 2020] [authz_core:error] [pid 5900:tid 1896] [client 192.168.1.3:53858] AH01630: client denied by server configuration: C:/xampp/htdocs/~snow
did you configure xamp server?? you have to change some configuration in “php.ini” and in “sendmail.ini”.
It’s the best thing I saw in login tutorials. But the truth, everyone who asks needs to try a little more to search info on google. An example for those who have problems with mail from localhost. I use xamp and it already comes with a sendmail addon. this url can help you. http://albertotain.blogspot.com/2018/02/como-configurar-xampp-para-enviar.html. It is in Spanish but you can use the translator.
For those that no have time to translate.
Config for Xamp server
Step 1: go to the php.ini file at the path C: \ xampp \ php \ php.ini
Step 2: find the line; extension = php_openssl.dll and remove the semicolon
Step 3: find the SMTP, smtp_post, sendmail_from and sendmail_path lines and put the following if you will use gmail as smtp:
SMTP = smtp.gmail.com
smtp_port = 587
sendmail_from = [email protected]
sendmail_path = “\” C: \ xampp \ sendmail \ sendmail.exe \ “-t”
If you copy and paste be careful with the quotes because the correct quote may not be inserted.
Step 4: open the sendmail.ini file located at the path C: \ xampp \ sendmail \ sendmail.ini and configure it as follows:
smtp_server = smtp.gmail.com
smtp_port = 587
error_logfile = error.log
debug_logfile = debug.log
[email protected]
auth_password = xxxxx
[email protected]
Step 5: if you use gmail to send emails locally you must have the account that you must activate the option “Allow less secure applications to access your account” otherwise you will not be able to send emails with gmail, I leave the link https : //support.google.com/accounts/answer/6010255? hl = en-419
need help
What?
The whole project works except that I receive the same message as I register a new email and it does not skip me to the verification activity. However, register and send me the mail.
same, does anyone can help us ?
Maybe you are getting any error. first check this api to postman app.
the message is that can use the mail because is in use
Hello It is not sending Mail on live host. Pls help Verification and reset password.
Very good explanation.
I copied all files to my project, but I’m unable to assign MyApplication as the startscreen. It refuses in the manifest files.
What am I doing wrong?
All compiled with success.
Manifest file : http://prntscr.com/tpb2sd
I’m getting this error when trying to register:
W/System.err: org.json.JSONException: Value <br of type java.lang.String cannot be converted to JSONObject
W/System.err: at org.json.JSON.typeMismatch(JSON.java:112)
W/System.err: at org.json.JSONObject.(JSONObject.java:169)
at org.json.JSONObject.(JSONObject.java:182)
at com.example.android_login.RegisterActivity.lambda$registerUser$2$RegisterActivity(RegisterActivity.java:92)
at com.example.android_login.-$$Lambda$RegisterActivity$qdOjFYQokWmNALZZ9DYPuxf6hIc.onResponse(Unknown Source:6)
at com.android.volley.toolbox.StringRequest.deliverResponse(StringRequest.java:78)
at com.android.volley.toolbox.StringRequest.deliverResponse(StringRequest.java:30)
at com.android.volley.ExecutorDelivery$ResponseDeliveryRunnable.run(ExecutorDelivery.java:106)
at android.os.Handler.handleCallback(Handler.java:938)
W/System.err: at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7523)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:941)
Hello It is not sending Mail on live host. Pls help Verification and reset password. I am stuck. But i receive the otp on phpmyadmin
when run .php error ” {“message”:”Method not supported!”} “
when access login.php by url message ” {“message”:”Method not supported!”} ” and second I register new user no err but data not found on mysql database . I am testing this on live server and giving live server local ip not public ip. kindly assist .
send screenshot to our facebook page or whatsapp number. so we can help you.
Add Profile picture and edit profile