Android Login Session System dengan Verifikasi Email (2)

Join Komunitas TipsKoding.com

5.  Langkah berikutnya mari kita buat Project Android

  • Buka android studio buat sebuah project baru melalui menu File > New Project dan setelah terbuka jendela isi kolom yang tersedia sesuai kebutuhan.
  • Buka build.gradle dan tambahkan volley library dalam dependencies.

[javascript]
dependencies {
compile fileTree(dir: ‘libs’, include: [‘*.jar’])
compile ‘com.android.support:appcompat-v7:28.0.0’
compile ‘com.android.support:design:28.0.0’
compile ‘com.android.support.constraint:constraint-layout:1.1.3’
compile ‘com.android.volley:volley:1.1.0’
}
[/javascript]

  • Berikut adalah struktur akhir package dari aplikasi login system yang akan kita buat
  • Buatlah package helper dalam package utama aplikasi kita, lalu yang buat sebuah file java dengan nama Functions.java dan berikut kodenya. Dengan file java tersebut kita akan mendeklarasikan URL API untuk login, registration, verifikasi email dan reset password. Silahkan isi IP address dengan IP localhost komputer kamu.

[php]
package com.tipskoding.login.helper;
import android.app.Activity;
import android.content.Context;
import android.view.inputmethod.InputMethodManager;
public class Functions {
//URL Utama
private static String MAIN_URL = "https://www.tipskoding.com/android_login/";
//URL Login
public static String LOGIN_URL = MAIN_URL + "login.php";
//URL Register
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";
/**
* Function untuk logout user
* Resets temporary data disimpan dalam SQLite Database
* */
public boolean logoutUser(Context context){
DatabaseHandler db = new DatabaseHandler(context);
db.resetTables();
return true;
}
/**
* Validasi Email Address
*/
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();
}
/**
* Menyembunyikan Keyboard
*/
public static void hideSoftKeyboard(Activity activity) {
InputMethodManager inputMethodManager =
(InputMethodManager) activity.getSystemService(
Activity.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(
activity.getCurrentFocus().getWindowToken(), 0);
}
}
[/php]

  • Buat file java dengan nama MyApplication.java. Class MyApplication ini merupakan extends dari Application yang akan dieksekusi ketika aplikasi dijalankan. Dalam class MyApplication menginisiasi semua object ini volley.

[javascript]
package com.tipskoding.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;
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 <T> void addToRequestQueue(Request<T> req, String tag) {
req.setTag(TextUtils.isEmpty(tag) ? TAG : tag);
getRequestQueue().add(req);
}
public <T> void addToRequestQueue(Request<T> req) {
req.setTag(TAG);
getRequestQueue().add(req);
}
public void cancelPendingRequests(Object tag) {
if (mRequestQueue != null) {
mRequestQueue.cancelAll(tag);
}
}
}
[/javascript]

  • Dalam package helper buat lagi file java dengan nama SessionManager.java dan gunakan kode berikut ini. Dalam class SessionManager ini mengelola data session dalam aplikasi menggunakan SharedPreferences. Kita menyimpan sebuah tanda boolean isLoggedIn dalam SharedPreferences untuk mengecek status login.

[javascript]
package com.tipskoding.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);
}
}
[/javascript]

  • Selanjutnya dalam package helper buat file DatabaseHandler.java dan gunakan kode berikut.

[javascript]
package com.tipskoding.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;
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,String>();
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;
}
/**
* Getting user login status
* return true if rows are there in table
* */
public int getRowCount() {
String countQuery = "SELECT * FROM " + TABLE_LOGIN;
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery(countQuery, null);
int rowCount = cursor.getCount();
db.close();
cursor.close();
// return row count
return rowCount;
}
/**
* 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();
}
}
[/javascript]

  • Membuat Tampilan untuk Reset Password
    Buat sebuah XML layout dengan nama reset_password.xml dalam folder res > layout.

Berikut script XML untuk reset_password.xml.

[javascript]
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="20dp">
<Button
android:id="@+id/logout"
android:layout_width="160dp"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentBottom="true"
android:layout_marginEnd="0dp"
android:layout_marginBottom="2dp"
android:background="#F44336"
android:text="@string/logout"
android:textColor="@color/white" />
<Button
android:id="@+id/change_password"
android:layout_width="160dp"
android:layout_height="wrap_content"
android:layout_above="@+id/logout"
android:layout_alignParentStart="true"
android:layout_marginStart="2dp"
android:layout_marginBottom="-48dp"
android:background="@color/colorPrimary"
android:text="@string/change_password"
android:textColor="@color/white" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_marginStart="0dp"
android:layout_marginTop="0dp"
android:gravity="top|center"
android:orientation="vertical">
<ImageView
android:id="@+id/imageView"
android:layout_width="match_parent"
android:layout_height="109dp"
app:srcCompat="@drawable/tipskodingsplash" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="60dp"
android:text="@string/welcome"
android:textSize="20sp" />
<TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
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>
</RelativeLayout>
[/javascript]

  • Menambahkan tampilan login. Buat file XML dengan nama activity_login.xml dalam folder res > layout.

[javascript]
<?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"
android:gravity="center">
<android.support.design.widget.TextInputLayout
android:id="@+id/lTextEmail"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp" >
<EditText
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"/>
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:id="@+id/lTextPassword"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp" >
<EditText
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"/>
</android.support.design.widget.TextInputLayout>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/login"
android:layout_marginTop="20dp"
android:background="@color/colorPrimary"
android:textColor="@color/white"
android:id="@+id/btnLogin"/>
<Button
android:id="@+id/btnLinkToRegisterScreen"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="40dip"
android:background="@null"
android:text="Register"
android:textAllCaps="false"
android:textColor="@color/colorPrimary"
android:textSize="13sp" />
<Button
android:id="@+id/btnForgotPassword"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:background="@null"
android:text="Forgot Password"
android:textAllCaps="false"
android:textColor="@color/colorPrimary"
android:textSize="13sp" />
</LinearLayout>
[/javascript]

  • Buat sebuah activity dengan nama LoginActivity.java.

[javascript]
package com.tipskoding.login;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.support.design.widget.TextInputLayout;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
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 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 org.json.JSONException;
import org.json.JSONObject;
import com.tipskoding.login.helper.DatabaseHandler;
import com.tipskoding.login.helper.Functions;
import com.tipskoding.login.helper.SessionManager;
import java.util.HashMap;
import java.util.Map;
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 Button 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 = (TextInputLayout) findViewById(R.id.lTextEmail);
inputPassword = (TextInputLayout) findViewById(R.id.lTextPassword);
btnLogin = (Button) findViewById(R.id.btnLogin);
btnLinkToRegister = (Button) findViewById(R.id.btnLinkToRegisterScreen);
btnForgotPass = (Button) 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() &amp;&amp; !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 = (TextInputLayout) 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() &gt; 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&lt;String&gt;() {
@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&lt;String, String&gt; getParams() {
// Posting parameters to login url
Map&lt;String, String&gt; params = new HashMap&lt;String, String&gt;();
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&lt;String&gt;() {
@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&lt;String, String&gt; getParams() {
// Posting parameters to login url
Map&lt;String, String&gt; params = new HashMap&lt;&gt;();
params.put("tag", "forgot_pass");
params.put("email", email);
return params;
}
@Override
public Map&lt;String, String&gt; getHeaders() throws AuthFailureError {
Map&lt;String, String&gt; params = new HashMap&lt;&gt;();
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();
}
}
[/javascript]

  • Selanjutnya buat layout untuk verifikasi email dengan nama activity_email_verify.xml dalam folder res > layout.

[javascript]
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="16dp">
<android.support.design.widget.TextInputLayout
android:id="@+id/verify_code"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="30dp">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="20dp"
android:hint="@string/verification_code"
android:inputType="number"/>
</android.support.design.widget.TextInputLayout>
<Button
android:id="@+id/btnVerify"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/colorPrimary"
android:textColor="@color/white"
android:text="@string/verify"/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:background="@null"
android:textColor="@color/borderless_button"
android:text="@string/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"/>
<EditText
android:id="@+id/editText2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textMultiLine"
android:padding="20dp"
android:textColor="@android:color/darker_gray"
tools:text="Cek Folder Spam jika email tidak otomatis masuk ke inbox, coba resend code jika email belum kamu terima." />
</LinearLayout>
[/javascript]

  • Buat class activity dengan nama EmailVerify.java.

[javascript]
package com.tipskoding.login;
import android.annotation.SuppressLint;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.support.design.widget.TextInputLayout;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
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 org.json.JSONException;
import org.json.JSONObject;
import com.tipskoding.login.helper.DatabaseHandler;
import com.tipskoding.login.helper.Functions;
import com.tipskoding.login.helper.SessionManager;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
public class EmailVerify extends AppCompatActivity {
private static final String TAG = EmailVerify.class.getSimpleName();
private TextInputLayout textVerifyCode;
private Button 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 = (TextInputLayout) findViewById(R.id.verify_code);
btnVerify = (Button) findViewById(R.id.btnVerify);
btnResend = (Button) findViewById(R.id.btnResendCode);
otpCountDown = (TextView) 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&lt;String&gt;() {
@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&lt;String, String&gt; getParams() {
// Posting parameters to login url
Map&lt;String, String&gt; params = new HashMap&lt;&gt;();
params.put("tag", "verify_code");
params.put("email", email);
params.put("otp", otp);
return params;
}
@Override
public Map&lt;String, String&gt; getHeaders() throws AuthFailureError {
Map&lt;String,String&gt; params = new HashMap&lt;String, String&gt;();
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&lt;String&gt;() {
@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&lt;String, String&gt; getParams() {
// Posting parameters to login url
Map&lt;String, String&gt; params = new HashMap&lt;String, String&gt;();
params.put("tag", "resend_code");
params.put("email", email);
return params;
}
@Override
public Map&lt;String, String&gt; getHeaders() throws AuthFailureError {
Map&lt;String,String&gt; params = new HashMap&lt;String, String&gt;();
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();
}
}
[/javascript]

Method db.addUser() yang bertugas untuk menyimpan data user dalam database SQLite ketika proses verifikasi email berhasil.

  • Selanjutnya membuat layout atau tampilan utama aplikasi. Setelah selesai membuat tampilan login, registrasi dan verifikasi, sekarang kita membuat tampilan terakhir yang akan menampilkan infromasi user yang berhasil login (logged in user information). Informasi tersebut diambil dari database SQLite setelah user berhasil login. Terdapat dua tombol untuk logout untuk menghentikan login session dan tombol untuk merubah password. Buatlah file dengan nama activity_home.xml dalam folder res > layout.

[javascript]
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="20dp">
<Button
android:id="@+id/logout"
android:layout_width="160dp"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentBottom="true"
android:layout_marginEnd="0dp"
android:layout_marginBottom="2dp"
android:background="#F44336"
android:text="@string/logout"
android:textColor="@color/white" />
<Button
android:id="@+id/change_password"
android:layout_width="160dp"
android:layout_height="wrap_content"
android:layout_above="@+id/logout"
android:layout_alignParentStart="true"
android:layout_marginStart="2dp"
android:layout_marginBottom="-48dp"
android:background="@color/colorPrimary"
android:text="@string/change_password"
android:textColor="@color/white" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_marginStart="0dp"
android:layout_marginTop="0dp"
android:gravity="top|center"
android:orientation="vertical">
<ImageView
android:id="@+id/imageView"
android:layout_width="match_parent"
android:layout_height="109dp"
app:srcCompat="@drawable/tipskodingsplash" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="60dp"
android:text="@string/welcome"
android:textSize="20sp" />
<TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
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>
</RelativeLayout>
[/javascript]

>> Langkah selanjutnya >>

Join Komunitas TipsKoding.com

Facebook Comments

POST A COMMENT.