Android Form Validator

Kemarin nih ada kerjaan bikin aplikasi android, yah biasa se ketemu masalah dasar yaitu form validasi, sebenernya kita bisa validasi data di server karena kebetulan kita bikin API untuk simpan data di database, but kita ndak mau harus bolak – balik karena user salah input nama pake angka, dan memang best practice nya validasinya di Android kecuali untuk hal – hal yang harus di cek di server misal availability username, email atau cek password kalo mau update setting profile akun, cek unique slug article atau kasus yang lain lah. Nah banyak nih yang bisa dipakai untuk validasi, iya pake library, kita bisa cari di Android Arsenal atau cari lewat google (bing, yahoo, dan yang lain) juga bisa.

Salah satu yang bisa dipake adalah library Saripaar (UI form validation library for Android). Library tersebut cukup lengkap, tapi disini aku gak bahas library, tapi bikin aku bikin kelas helper untuk Android Validator sendiri, yah ndak perlu bagus penting bisa dan selama kita butuh yang standard kenapa harus pake source code berlebih dari library, kecuali kita punya aplikasi yang akan berkembang kompleks dan tau dimasa yang akan datang akan semakin rumit dalam meng-handle form maka ndak masalah boleh aja pake library. Oke kita bikin class yang isinya fungsi untuk validasi, aku nulis codingnya di Gist jadi aku embed aja disini.

Ada 2 file dibawah ini, file Validator.java yaitu class helper yang berisi kumpulan method untuk validasi, dan kelas Unit Testing, ndak perlu dipedulikan, itu cuma test case yang aku bikin, tapi dari file test itu kalian bisa liat cara aku panggi semua method validasi tersebut. Kalian bisa buka dafatar Gist ku disini dan akun github ku sendiri disini. Semoga bermafaat.

Daftar rule validasi yang di cover class ini adalah required, url, email, person name, alpha-dash (username), date, min, max, range number dan string, custom regexp, memberOf, uniqueOf, dan tambahan method untuk convert string menjadi slug. Silahkan tambahkan fungsi kalian sendiri jika perlu (misal format CC) jangan lupa kalau ingin ngasih kontribusi kirim pull request atau message di github agar fungsinya lebih banyak 🙂

package com.sketchproject.infogue.modules;
import android.util.Log;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Locale;
/**
* Helper class to validate the inputs, still find a way to manage multiple input with internal
* validation so user just passing the input and return the errors message,
* but still working on it :).
* <p>
* Sketch Project Studio
* Created by Angga on 16/04/2016 13.29.
*/
public class Validator {
/**
* Find out the object is empty.
*
* @param value general input
* @return boolean
*/
public boolean isEmpty(Object value) {
return isEmpty(value, false);
}
/**
* Check if object is empty or not, null, blank, 0, false is empty
* depends on data type or how the object can be casted.
*
* @param value needs to be checked
* @param isIgnoreSpace is include space or not
* @return boolean
*/
public boolean isEmpty(Object value, boolean isIgnoreSpace) {
if (value == null) {
return true;
} else if (value instanceof Boolean) {
return !((Boolean) value);
} else if (value instanceof String) {
if (isIgnoreSpace) {
return String.valueOf(value).trim().isEmpty();
}
return String.valueOf(value).isEmpty();
} else {
try {
int result = Integer.parseInt(value.toString());
return result == 0;
} catch (NumberFormatException e) {
return false;
}
}
}
/**
* Check if email string is valid format.
*
* @param email input string
* @return boolean email format validation
*/
public boolean isValidEmail(String email) {
return android.util.Patterns.EMAIL_ADDRESS.matcher(email).matches();
}
/**
* Check if string accept as url format, still imperfect but i'm working on it.
*
* @param url input string
* @return boolean url format is valid or not
*/
public boolean isValidUrl(String url) {
String urlPattern = "^(https?|ftp|file)://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|]";
return url.matches(urlPattern);
}
/**
* Check if string only contains alpha dash numeric underscore and hyphen.
*
* @param value input string
* @return boolean
*/
public boolean isAlphaDash(String value) {
return value.matches("^[a-zA-Z0-9-_]*$");
}
/**
* Check if string only contain alpha dash.
*
* @param value input string
* @return boolean
*/
public boolean isAlphaNumeric(String value) {
return value.matches("^[a-zA-Z0-9]*$");
}
/**
* Person name limit character alphabet and some punctuations.
*
* @param value input string
* @return boolean
*/
public boolean isPersonName(String value) {
return value.matches("^[a-zA-Z '.,]*$");
}
/**
* Check if date string can be parse to date format.
*
* @param date input string
* @return boolean
*/
public boolean isValidDate(String date) {
try {
DateFormat df = new SimpleDateFormat("yyyy-mm-dd", Locale.getDefault());
df.setLenient(false);
df.parse(date);
return true;
} catch (ParseException e) {
Log.e("Parse Date Exception", e.getMessage());
return false;
}
}
/**
* Check if input string only contain signed numeric.
*
* @param value input string
* @return boolean
*/
public boolean isNumeric(Object value) {
return isNumeric(value, false);
}
/**
* Check if input string only contain numeric signed and unsigned number depends on parameter.
*
* @param value input string
* @param isSignedOnly is allow signed number only or both
* @return boolean
*/
public boolean isNumeric(Object value, boolean isSignedOnly) {
try {
int result = Integer.parseInt(value.toString());
return !isSignedOnly || result >= 0;
} catch (NumberFormatException e) {
return false;
}
}
/**
* Check is input has minimum characters including space.
*
* @param value input string
* @param minValue min length of characters
* @return boolean
*/
public boolean minLength(String value, int minValue) {
return minLength(value, minValue, false);
}
/**
* Check is input has minimum characters.
*
* @param value input string
* @param minValue min length of characters
* @param ignoreSpace count character without space or empty string
* @return boolean
*/
public boolean minLength(String value, int minValue, boolean ignoreSpace) {
if (ignoreSpace) {
return String.valueOf(value).trim().length() >= minValue;
}
return String.valueOf(value).length() >= minValue;
}
/**
* Check is input reach maximum characters.
*
* @param value input string
* @param maxValue number of maximum characters
* @return boolean
*/
public boolean maxLength(String value, int maxValue) {
return maxLength(value, maxValue, false);
}
/**
* Check is input reach maximum characters.
*
* @param value input string
* @param maxValue number of maximum characters
* @param ignoreSpace count characters exclude space or empty string
* @return boolean
*/
public boolean maxLength(String value, int maxValue, boolean ignoreSpace) {
if (ignoreSpace) {
return String.valueOf(value).trim().length() <= maxValue;
}
return String.valueOf(value).length() <= maxValue;
}
/**
* Check character in range minimum and maximum characters.
*
* @param value input string
* @param minValue number of minimum characters
* @param maxValue number of maximum characters
* @return boolean
*/
public boolean rangeLength(String value, int minValue, int maxValue) {
return rangeLength(value, minValue, maxValue, false);
}
/**
* Check character in range minimum and maximum characters with ignoring
* space and empty string option.
*
* @param value input string
* @param minValue number of minimum characters
* @param maxValue number of maximum characters
* @param isIgnoreSpace ignoring space or empty string
* @return boolean
*/
public boolean rangeLength(String value, int minValue, int maxValue, boolean isIgnoreSpace) {
String string = String.valueOf(value);
if (isIgnoreSpace) {
return string.trim().length() >= minValue && string.trim().length() <= maxValue;
}
return string.length() >= minValue && string.length() <= maxValue;
}
/**
* Check minimum integer value.
*
* @param value input string
* @param minValue number of minimum value
* @return boolean
*/
public boolean minValue(int value, int minValue) {
return value >= minValue;
}
/**
* Check minimum float value.
*
* @param value input string
* @param minValue number of minimum value
* @return boolean
*/
public boolean minValue(float value, float minValue) {
return value >= minValue;
}
/**
* Check minimum double value.
*
* @param value input string
* @param minValue number of minimum value
* @return boolean
*/
public boolean minValue(double value, double minValue) {
return value >= minValue;
}
/**
* Check maximum integer value.
*
* @param value input string
* @param maxValue number of maximum value
* @return boolean
*/
public boolean maxValue(int value, int maxValue) {
return value <= maxValue;
}
/**
* Check maximum float value.
*
* @param value input string
* @param maxValue number of maximum value
* @return boolean
*/
public boolean maxValue(float value, float maxValue) {
return value <= maxValue;
}
/**
* Check maximum double value.
*
* @param value input string
* @param maxValue number of maximum value
* @return boolean
*/
public boolean maxValue(double value, double maxValue) {
return value <= maxValue;
}
/**
* Check integer value in range.
*
* @param value input string
* @param minValue number of minimum value
* @param maxValue number of maximum value
* @return boolean
*/
public boolean rangeValue(int value, int minValue, int maxValue) {
return value >= minValue && value <= maxValue;
}
/**
* Check float value in range.
*
* @param value input string
* @param minValue number of minimum value
* @param maxValue number of maximum value
* @return boolean
*/
public boolean rangeValue(float value, float minValue, float maxValue) {
return value >= minValue && value <= maxValue;
}
/**
* Check double value in range.
*
* @param value input string
* @param minValue number of minimum value
* @param maxValue number of maximum value
* @return boolean
*/
public boolean rangeValue(double value, double minValue, double maxValue) {
return value >= minValue && value <= maxValue;
}
/**
* Check if string is not member of collection data.
*
* @param value input string
* @param dataSet collection of string data
* @return boolean
*/
public boolean isUnique(String value, String[] dataSet) {
for (String data : dataSet) {
if (data.equals(value)) {
return false;
}
}
return true;
}
/**
* Check if integer is not member of collection data.
*
* @param value input integer
* @param dataSet collection of integer data
* @return boolean
*/
public boolean isUnique(int value, int[] dataSet) {
for (int data : dataSet) {
if (data == value) {
return false;
}
}
return true;
}
/**
* Check if a string member of data set, ignoring number of data matched.
*
* @param value input string
* @param dataSet collection of string data
* @return boolean
*/
public boolean isMemberOf(String value, String[] dataSet) {
for (String data : dataSet) {
if (data.equals(value)) {
return true;
}
}
return false;
}
/**
* Check if a integer member of data set, ignoring number of data matched.
*
* @param value input string
* @param dataSet collection of integer data
* @return boolean
*/
public boolean isMemberOf(int value, int[] dataSet) {
for (int data : dataSet) {
if (data == value) {
return true;
}
}
return false;
}
/**
* Custom rule by passing regular expression.
*
* @param value input string
* @param regex rule
* @return boolean
*/
public boolean isValid(String value, String regex) {
return value.matches(regex);
}
/**
* Build slug from string title like "The beautiful day in 1992" turns "the-beautiful-day-in-1992"
* or "Super massive black hole O'creaz MO on July" turns "super-massive-black-hole-o-creaz-mo-on-july"
*
* @param title article title
* @return slug string
*/
public String createSlug(String title) {
String trimmed = title.trim();
String slug = trimmed
.replaceAll("[^a-zA-Z0-9-]", "")
.replaceAll("-+", "")
.replaceAll("^-|-$", "");
return slug.toLowerCase();
}
/**
* Convenience contract template used to validate process
*/
public interface ViewValidation {
/**
* Use for populate inputs before validation.
*/
void preValidation();
/**
* Check input with rules here.
*
* @return boolean
*/
boolean onValidateView();
/**
* Do something after validate the inputs.
*
* @param isValid status validation could be achieved by run onValidateView and
* passing accumulate of success and fail result validator method.
*/
void postValidation(boolean isValid);
}
}

view raw
Validator.java
hosted with ❤ by GitHub

package com.sketchproject.infogue.modules;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Sketch Project Studio
* Created by Angga on 02/05/2016 15.40.
*/
public class ValidatorTest {
Validator validator;
@Before
public void setUp() throws Exception {
validator = new Validator();
}
@After
public void tearDown() throws Exception {
validator = null;
}
@Test
public void testIsEmpty() throws Exception {
assertTrue(validator.isEmpty(""));
assertTrue(validator.isEmpty(0));
assertTrue(validator.isEmpty(null));
assertTrue(validator.isEmpty(false));
}
@Test
public void testIsEmptyIgnoreSpace() throws Exception {
assertTrue(validator.isEmpty(" ", true));
assertTrue(validator.isEmpty(0, true));
assertTrue(validator.isEmpty(null, true));
assertTrue(validator.isEmpty(false, true));
}
@Test
public void testIsValidEmail() throws Exception {
/*
assertTrue(validator.isValidEmail("anggadarkprince@gmail.com"));
assertTrue(validator.isValidEmail("anggadarkprince@gmail"));
assertFalse(validator.isValidEmail("anggadarkprince"));
assertFalse(validator.isValidEmail("@gmail@yahoo@rocket"));
assertFalse(validator.isValidEmail("@gmail")); */
}
@Test
public void testIsValidUrl() throws Exception {
assertFalse(validator.isValidUrl("angga-ari.com"));
assertTrue(validator.isValidUrl("http://angga-ari.com"));
assertTrue(validator.isValidUrl("http://infogue.stage.angga-ari.com"));
assertTrue(validator.isValidUrl("https://angga-ari.com/public/account"));
assertTrue(validator.isValidUrl("ftp://angga-ari.com:8000"));
assertTrue(validator.isValidUrl("file://angga-ari.com/images/image.jpg"));
}
@Test
public void testIsAlphaDash() throws Exception {
assertTrue(validator.isAlphaDash("AnggaDarkPrince"));
assertTrue(validator.isAlphaDash("angga-ari2"));
assertTrue(validator.isAlphaDash("angga_ari43"));
assertFalse(validator.isAlphaDash("angga ari 43"));
assertFalse(validator.isAlphaDash("angga$$"));
}
@Test
public void testIsAlphaNumeric() throws Exception {
assertTrue(validator.isAlphaNumeric("Angga17"));
assertFalse(validator.isAlphaNumeric("Angga 17"));
assertFalse(validator.isAlphaNumeric("Angga_17"));
assertFalse(validator.isAlphaNumeric("Angga-17"));
assertFalse(validator.isAlphaNumeric("Angga-+&^*17"));
}
@Test
public void testIsPersonName() throws Exception {
assertTrue(validator.isPersonName("Angga Ari Wijaya"));
assertTrue(validator.isPersonName("O'brian"));
assertTrue(validator.isPersonName("Mr. Echo,msi"));
assertFalse(validator.isPersonName("angga v1.0"));
}
@Test
public void testIsValidDate() throws Exception {
assertTrue(validator.isValidDate("2015-08-12"));
assertFalse(validator.isValidDate("18-12-2015"));
assertFalse(validator.isValidDate("2015"));
assertFalse(validator.isValidDate("Blue Crimson"));
assertFalse(validator.isValidDate("Laa232"));
}
@Test
public void testIsNumeric() throws Exception {
assertTrue(validator.isNumeric(32));
assertFalse(validator.isNumeric("tes"));
}
@Test
public void testIsNumericSignedOnly() throws Exception {
assertTrue(validator.isNumeric(32, true));
assertFalse(validator.isNumeric(false));
assertFalse(validator.isNumeric(34, true));
assertTrue(validator.isNumeric(0, true));
assertTrue(validator.isNumeric(45, true));
}
@Test
public void testMinLength() throws Exception {
assertTrue(validator.minLength("Angga", 2));
assertFalse(validator.minLength("Angga", 10));
}
@Test
public void testMinLengthIgnoringSpace() throws Exception {
assertTrue(validator.minLength("A n g g a A r i", 8, true));
assertTrue(validator.minLength("Angga Ar i", 15, true));
assertFalse(validator.minLength("Angga", 8, true));
}
@Test
public void testMaxLength() throws Exception {
assertTrue(validator.maxLength("Angga", 5));
assertFalse(validator.maxLength("Angga Ari", 8));
}
@Test
public void testMaxLengthIgnoringSpace() throws Exception {
assertEquals(9, String.valueOf(" Angga Ari ").trim().length());
assertTrue(validator.maxLength("Angga", 5, true));
assertTrue(validator.maxLength("Angga Ari", 9, true));
}
@Test
public void testRangeLength() throws Exception {
assertTrue(validator.rangeLength("Angga", 2, 10));
assertFalse(validator.rangeLength("Angga", 6, 10));
assertFalse(validator.rangeLength("Angga Ari", 3, 5));
}
@Test
public void testRangeLengthIgnoringSpace() throws Exception {
assertTrue(validator.rangeLength(" Angga ", 2, 6, true));
assertFalse(validator.rangeLength(" Angga", 6, 10, true));
assertFalse(validator.rangeLength("Angga Ari", 3, 5, true));
}
@Test
public void testMinValue() throws Exception {
assertTrue(validator.minValue(3, 2));
assertTrue(validator.minValue(3f, 2f));
assertTrue(validator.minValue(3d, 2d));
assertFalse(validator.minValue(5, 10));
assertFalse(validator.minValue(7f, 8f));
assertFalse(validator.minValue(2d, 5d));
}
@Test
public void testMaxValue() throws Exception {
assertTrue(validator.maxValue(3, 5));
assertTrue(validator.maxValue(3f, 5f));
assertTrue(validator.maxValue(3d, 5d));
assertFalse(validator.maxValue(15, 10));
assertFalse(validator.maxValue(17f, 8f));
assertFalse(validator.maxValue(12d, 5d));
}
@Test
public void testRangeValue() throws Exception {
assertTrue(validator.rangeValue(3, 1, 5));
assertTrue(validator.rangeValue(3f, 1f, 5f));
assertTrue(validator.rangeValue(3d, 1, 5d));
assertFalse(validator.rangeValue(5, 6, 10));
assertFalse(validator.rangeValue(8f, 3f, 7f));
assertFalse(validator.rangeValue(2d, 5d, 8d));
}
@Test
public void testIsUnique() throws Exception {
int[] data = {32,34,23,54};
assertTrue(validator.isUnique(2, data));
assertFalse(validator.isUnique(23, data));
}
@Test
public void testIsUniqueString() throws Exception {
String[] data = {"angga","ari","wijaya"};
assertTrue(validator.isUnique("hana", data));
assertFalse(validator.isUnique("angga", data));
}
@Test
public void testIsMemberOf() throws Exception {
int[] data = {32,34,23,54};
assertTrue(validator.isMemberOf(32, data));
assertFalse(validator.isMemberOf(3, data));
}
@Test
public void testIsMemberOfString() throws Exception {
String[] data = {"angga","ari","wijaya"};
assertTrue(validator.isMemberOf("angga", data));
assertFalse(validator.isMemberOf("rio", data));
}
@Test
public void testIsValid() throws Exception {
assertTrue(validator.isValid("angga", "[a-zA-Z]*"));
assertFalse(validator.isValid("angga17", "[a-zA-Z]*"));
}
}

view raw
ValidatorTest.java
hosted with ❤ by GitHub

Thanks for giving me feedback and revision. – Angga Ari Wijaya

Tinggalkan Balasan

Isikan data di bawah atau klik salah satu ikon untuk log in:

Logo WordPress.com

You are commenting using your WordPress.com account. Logout /  Ubah )

Foto Google

You are commenting using your Google account. Logout /  Ubah )

Gambar Twitter

You are commenting using your Twitter account. Logout /  Ubah )

Foto Facebook

You are commenting using your Facebook account. Logout /  Ubah )

Connecting to %s