Académique Documents
Professionnel Documents
Culture Documents
HOME
HTTP
Tips
Write for Us
SEARCH HERE
VIDEO DEMO
DOWNLOAD CODE
AndroidHive
40,056likes
LikePage
Bethefirstofyourfriendstolikethis
Subscribe to
Newsletter
Join our 746,498
subscribers and get access
to the latest android
tutorials, freebies, scripts
and much more!
Sign Up
Android Login and Registration with PHP, MySQL and SQLite ...
Prerequisites
This tutorial is combination of few of my previous articles. Make sure you went
through the below articles if you are very beginner.
1. Android working with Volley Library Used to make HTTP calls.
2. Android Login and Registration Screen Design Explained the designing of
Login and Registration screens.
POPULAR ANDROID
TUTORIALS
To interact with MySQL database we need to build a REST API rst. REST Api job
is to get the request from client, interact with database and nally give the
response back to client. So well create a simple PHP, MySQL API rst. Our API
dos below jobs.
Accepts requests in GET/POST methods
Interact with database by inserting / fetching data.
Finally will give response back in JSON format
createdatabaseandroid_api/**CreatingDatabase**/
useandroid_api/**SelectingDatabase**/
createtableusers(
idint(11)primarykeyauto_increment,
unique_idvarchar(23)notnullunique,
namevarchar(50)notnull,
emailvarchar(100)notnullunique,
encrypted_passwordvarchar(80)notnull,
saltvarchar(10)notnull,
created_atdatetime,
updated_atdatetimenull
);/**CreatingUsersTable**/
1. Go into www folder and create a folder named android_login_api. This will
be the root directory of our project.
2. In android_login_api, create another directory named include. In this folder,
we keep all the helper classes.
3. Now inside include, create a php le named Cong.php and add below
content. Replace the DB_USER and DB_PASSWORD values with yours.
Config.php
<?php
/**
*Databaseconfigvariables
*/
define("DB_HOST","localhost");
define("DB_USER","root");
define("DB_PASSWORD","root");
define("DB_DATABASE","android_api");
?>
DB_Connect.php
<?php
classDB_Connect{
private$conn;
//Connectingtodatabase
publicfunctionconnect(){
require_once'include/Config.php';
//Connectingtomysqldatabase
$this>conn=newmysqli(DB_HOST,DB_USER,DB_PASSWORD,DB_DATABASE);
//returndatabasehandler
return$this>conn;
}
}
?>
<?php
/**
*@authorRaviTamada
*@linkhttp://www.androidhive.info/2012/01/androidloginandregistrationwithphpmysqla
*/
classDB_Functions{
private$conn;
//constructor
function__construct(){
require_once'DB_Connect.php';
//connectingtodatabase
$db=newDb_Connect();
$this>conn=$db>connect();
}
//destructor
function__destruct(){
/**
*Storingnewuser
*returnsuserdetails
*/
publicfunctionstoreUser($name,$email,$password){
$uuid=uniqid('',true);
$hash=$this>hashSSHA($password);
$encrypted_password=$hash["encrypted"];//encryptedpassword
$salt=$hash["salt"];//salt
$stmt=$this>conn>prepare("INSERTINTOusers(unique_id,name,email,encrypted_pa
$stmt>bind_param("sssss",$uuid,$name,$email,$encrypted_password
$result=$stmt>execute();
$stmt>close();
//checkforsuccessfulstore
if($result){
$stmt=$this>conn>prepare("SELECT*FROMusersWHEREemail=?"
$stmt>bind_param("s",$email);
$stmt>execute();
$user=$stmt>get_result()>fetch_assoc();
$stmt>close();
return$user;
}else{
returnfalse;
}
}
/**
*Getuserbyemailandpassword
*/
publicfunctiongetUserByEmailAndPassword($email,$password
$stmt=$this>conn>prepare("SELECT*FROMusersWHEREemail=?"
$stmt>bind_param("s",$email);
if($stmt>execute()){
$user=$stmt>get_result()>fetch_assoc();
$stmt>close();
//verifyinguserpassword
$salt=$user['salt'];
$encrypted_password=$user['encrypted_password'];
$hash=$this>checkhashSSHA($salt,$password);
//checkforpasswordequality
if($encrypted_password==$hash){
//userauthenticationdetailsarecorrect
return$user;
}
}else{
returnNULL;
}
}
/**
*Checkuserisexistedornot
*/
publicfunctionisUserExisted($email){
$stmt=$this>conn>prepare("SELECTemailfromusersWHEREemail=?"
$stmt>bind_param("s",$email);
$stmt>execute();
$stmt>store_result();
if($stmt>num_rows>0){
//userexisted
$stmt>close();
returntrue;
}else{
//usernotexisted
$stmt>close();
returnfalse;
}
}
/**
*Encryptingpassword
*@parampassword
*returnssaltandencryptedpassword
*/
publicfunctionhashSSHA($password){
$salt=sha1(rand());
$salt=substr($salt,0,10);
$encrypted=base64_encode(sha1($password.$salt,true).
$hash=array("salt"=>$salt,"encrypted"=>$encrypted
return$hash;
}
/**
*Decryptingpassword
*@paramsalt,password
*returnshashstring
*/
publicfunctioncheckhashSSHA($salt,$password){
$hash=base64_encode(sha1($password.$salt,true).$salt
return$hash;
}
?>
register.php
<?php
require_once'include/DB_Functions.php';
$db=newDB_Functions();
//jsonresponsearray
$response=array("error"=>FALSE);
if(isset($_POST['name'])&&isset($_POST['email'])&&isset($_POST
//receivingthepostparams
$name=$_POST['name'];
$email=$_POST['email'];
$password=$_POST['password'];
//checkifuserisalreadyexistedwiththesameemail
if($db>isUserExisted($email)){
//useralreadyexisted
$response["error"]=TRUE;
$response["error_msg"]="Useralreadyexistedwith".
echojson_encode($response);
}else{
//createanewuser
$user=$db>storeUser($name,$email,$password);
if($user){
//userstoredsuccessfully
$response["error"]=FALSE;
$response["uid"]=$user["unique_id"];
$response["user"]["name"]=$user["name"];
$response["user"]["email"]=$user["email"];
$response["user"]["created_at"]=$user["created_at"
$response["user"]["updated_at"]=$user["updated_at"
echojson_encode($response);
}else{
//userfailedtostore
$response["error"]=TRUE;
$response["error_msg"]="Unknownerroroccurredinregistration!"
echojson_encode($response);
}
}
}else{
$response["error"]=TRUE;
$response["error_msg"]="Requiredparameters(name,emailorpassword)ismissing!"
echojson_encode($response);
}
?>
login.php
<?php
require_once'include/DB_Functions.php';
$db=newDB_Functions();
//jsonresponsearray
$response=array("error"=>FALSE);
if(isset($_POST['email'])&&isset($_POST['password'])){
//receivingthepostparams
$email=$_POST['email'];
$password=$_POST['password'];
//gettheuserbyemailandpassword
$user=$db>getUserByEmailAndPassword($email,$password);
if($user!=false){
//useisfound
$response["error"]=FALSE;
$response["uid"]=$user["unique_id"];
$response["user"]["name"]=$user["name"];
$response["user"]["email"]=$user["email"];
$response["user"]["created_at"]=$user["created_at"];
$response["user"]["updated_at"]=$user["updated_at"];
echojson_encode($response);
}else{
//userisnotfoundwiththecredentials
$response["error"]=TRUE;
$response["error_msg"]="Logincredentialsarewrong.Pleasetryagain!"
echojson_encode($response);
}
}else{
//requiredpostparamsismissing
$response["error"]=TRUE;
$response["error_msg"]="Requiredparametersemailorpasswordismissing!"
echojson_encode($response);
}
?>
{
"error":false,
"uid":"55fa7220a2c187.50984590",
"user":{
"name":"RaviTamada",
"email":"ravi@androidhive.info",
"created_at":"2015091713:26:16",
"updated_at":null
}
}
{
"error":1,
"error_msg":"Unknownerroroccurredinregistration!"
}
{
"success":0,
"error":2,
"error_msg":"Useralreadyexistedwithravi8x@androidhive.info"
}
3.3.2 Login
URL: http://localhost/android_login_api/login.php
PARAMS: email, password
Login Success
{
"error":false,
"uid":"55fa7220a2c187.50984590",
"user":{
"name":"RaviTamada",
"email":"ravi@androidhive.info",
"created_at":"2015091713:26:16",
"updated_at":null
}
}
{
"tag":"login",
"success":0,
"error":1,
"error_msg":"Logincredentialsareincorrect.Pleasetryagain!"
}
Now we have completed the PHP part. Lets start the android part.
build.gradle
dependencies{
compile'com.android.support:appcompatv7:23.1.1'
compile'com.android.support:design:23.1.1'
compile'com.mcxiaoke.volley:libraryaar:1.0.0'
4. Open strings.xml located under res values and add below string values.
strings.xml
<?xmlversion="1.0"encoding="utf8"?>
<resources>
<stringname="app_name">AndroidLoginandRegistration</string
<stringname="hint_email">Email</string>
<stringname="hint_password">Password</string>
<stringname="hint_name">Fullname</string>
<stringname="btn_login">LOGIN</string>
<stringname="btn_register">REGISTER</string>
<stringname="btn_link_to_register">Notamember?Signupnow.</
<stringname="btn_link_to_login">Alreadyregistred!LoginMe.</
<stringname="welcome">Welcome</string>
<stringname="btn_logout">LOGOUT</string>
<stringname="name">Fullname</string>
</resources>
5. Open colors.xml located under res values and add the color values. If you
dont nd colors.xml, create a new le with the name.
colors.xml
<?xmlversion="1.0"encoding="utf8"?>
<resources>
<colorname="bg_login">#26ae90</color>
<colorname="bg_register">#2e3237</color>
<colorname="bg_main">#428bca</color>
<colorname="white">#ffffff</color>
<colorname="input_login">#222222</color>
<colorname="input_login_hint">#999999</color>
<colorname="input_register">#888888</color>
<colorname="input_register_bg">#3b4148</color>
<colorname="input_register_hint">#5e6266</color>
<colorname="btn_login">#26ae90</color>
<colorname="btn_login_bg">#eceef1</color>
<colorname="lbl_name">#333333</color>
<colorname="btn_logut_bg">#ff6861</color>
</resources>
6. Under app package create a class named AppCong.java and add below
code. In this class we declare the login and registration urls. While testing you
need to replace the ip address with your localhost pc ip.
AppConfig.java
packageinfo.androidhive.loginandregistration.app;
publicclassAppConfig{
//Serveruserloginurl
publicstaticStringURL_LOGIN="http://192.168.0.102/android_login_api/login.php
//Serveruserregisterurl
publicstaticStringURL_REGISTER="http://192.168.0.102/android_login_api/register.php
}
AppController.java
packageinfo.androidhive.loginandregistration.app;
importandroid.app.Application;
importandroid.text.TextUtils;
importcom.android.volley.Request;
importcom.android.volley.RequestQueue;
importcom.android.volley.toolbox.Volley;
publicclassAppControllerextendsApplication{
publicstaticfinalStringTAG=AppController.class.getSimpleName();
privateRequestQueuemRequestQueue;
privatestaticAppControllermInstance;
@Override
publicvoidonCreate(){
super.onCreate();
mInstance=this;
}
publicstaticsynchronizedAppControllergetInstance(){
returnmInstance;
}
publicRequestQueuegetRequestQueue(){
if(mRequestQueue==null){
mRequestQueue=Volley.newRequestQueue(getApplicationContext());
}
returnmRequestQueue;
}
public<T>voidaddToRequestQueue(Request<T>req,Stringtag){
req.setTag(TextUtils.isEmpty(tag)?TAG:tag);
getRequestQueue().add(req);
}
public<T>voidaddToRequestQueue(Request<T>req){
req.setTag(TAG);
getRequestQueue().add(req);
}
publicvoidcancelPendingRequests(Objecttag){
if(mRequestQueue!=null){
mRequestQueue.cancelAll(tag);
}
}
}
AndroidManifest.xml
<?xmlversion="1.0"encoding="utf8"?>
<manifestxmlns:android="http://schemas.android.com/apk/res/android
package="info.androidhive.loginandregistration"
android:versionCode="1"
android:versionName="1.0">
<usessdk
android:minSdkVersion="9"
android:targetSdkVersion="21"/>
<usespermissionandroid:name="android.permission.INTERNET"
<application
android:name="info.androidhive.loginandregistration.app.AppController"
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme">
<activity
android:name=".LoginActivity"
android:label="@string/app_name"
android:launchMode="singleTop"
android:windowSoftInputMode="adjustPan">
<intentfilter>
<actionandroid:name="android.intent.action.MAIN"
<categoryandroid:name="android.intent.category.LAUNCHER"
</intentfilter>
</activity>
<activity
android:name=".RegisterActivity"
android:label="@string/app_name"
android:launchMode="singleTop"
android:windowSoftInputMode="adjustPan"/>
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:launchMode="singleTop"/>
</application>
</manifest>
SessionManager.java
packageinfo.androidhive.loginandregistration.helper;
importandroid.content.Context;
importandroid.content.SharedPreferences;
importandroid.content.SharedPreferences.Editor;
importandroid.util.Log;
publicclassSessionManager{
//LogCattag
privatestaticStringTAG=SessionManager.class.getSimpleName();
//SharedPreferences
SharedPreferencespref;
Editoreditor;
Context_context;
//Sharedprefmode
intPRIVATE_MODE=0;
//Sharedpreferencesfilename
privatestaticfinalStringPREF_NAME="AndroidHiveLogin";
privatestaticfinalStringKEY_IS_LOGGEDIN="isLoggedIn";
publicSessionManager(Contextcontext){
this._context=context;
pref=_context.getSharedPreferences(PREF_NAME,PRIVATE_MODE);
editor=pref.edit();
}
publicvoidsetLogin(booleanisLoggedIn){
editor.putBoolean(KEY_IS_LOGGEDIN,isLoggedIn);
//commitchanges
editor.commit();
Log.d(TAG,"Userloginsessionmodified!");
}
publicbooleanisLoggedIn(){
returnpref.getBoolean(KEY_IS_LOGGEDIN,false);
}
}
SQLiteHandler.java
/**
*Author:RaviTamada
*URL:www.androidhive.info
*twitter:http://twitter.com/ravitamada
**/
packageinfo.androidhive.loginandregistration.helper;
importandroid.content.ContentValues;
importandroid.content.Context;
importandroid.database.Cursor;
importandroid.database.sqlite.SQLiteDatabase;
importandroid.database.sqlite.SQLiteOpenHelper;
importandroid.util.Log;
importjava.util.HashMap;
publicclassSQLiteHandlerextendsSQLiteOpenHelper{
privatestaticfinalStringTAG=SQLiteHandler.class.getSimpleName();
//AllStaticvariables
//DatabaseVersion
privatestaticfinalintDATABASE_VERSION=1;
//DatabaseName
privatestaticfinalStringDATABASE_NAME="android_api";
//Logintablename
privatestaticfinalStringTABLE_USER="user";
//LoginTableColumnsnames
privatestaticfinalStringKEY_ID="id";
privatestaticfinalStringKEY_NAME="name";
privatestaticfinalStringKEY_EMAIL="email";
privatestaticfinalStringKEY_UID="uid";
privatestaticfinalStringKEY_CREATED_AT="created_at";
publicSQLiteHandler(Contextcontext){
super(context,DATABASE_NAME,null,DATABASE_VERSION);
}
//CreatingTables
@Override
publicvoidonCreate(SQLiteDatabasedb){
StringCREATE_LOGIN_TABLE="CREATETABLE"+TABLE_USER+
+KEY_ID+"INTEGERPRIMARYKEY,"+KEY_NAME+
+KEY_EMAIL+"TEXTUNIQUE,"+KEY_UID+"TEXT,"
+KEY_CREATED_AT+"TEXT"+")";
db.execSQL(CREATE_LOGIN_TABLE);
Log.d(TAG,"Databasetablescreated");
}
//Upgradingdatabase
@Override
publicvoidonUpgrade(SQLiteDatabasedb,intoldVersion,int
//Dropoldertableifexisted
db.execSQL("DROPTABLEIFEXISTS"+TABLE_USER);
//Createtablesagain
onCreate(db);
}
/**
*Storinguserdetailsindatabase
**/
publicvoidaddUser(Stringname,Stringemail,Stringuid,Stringcreated_at){
SQLiteDatabasedb=this.getWritableDatabase();
ContentValuesvalues=newContentValues();
values.put(KEY_NAME,name);//Name
values.put(KEY_EMAIL,email);//Email
values.put(KEY_UID,uid);//Email
values.put(KEY_CREATED_AT,created_at);//CreatedAt
//InsertingRow
longid=db.insert(TABLE_USER,null,values);
db.close();//Closingdatabaseconnection
Log.d(TAG,"Newuserinsertedintosqlite:"+id);
}
/**
*Gettinguserdatafromdatabase
**/
publicHashMap<String,String>getUserDetails(){
HashMap<String,String>user=newHashMap<String,String>();
StringselectQuery="SELECT*FROM"+TABLE_USER;
SQLiteDatabasedb=this.getReadableDatabase();
Cursorcursor=db.rawQuery(selectQuery,null);
//Movetofirstrow
cursor.moveToFirst();
if(cursor.getCount()>0){
user.put("name",cursor.getString(1));
user.put("email",cursor.getString(2));
user.put("uid",cursor.getString(3));
user.put("created_at",cursor.getString(4));
}
cursor.close();
db.close();
//returnuser
Log.d(TAG,"FetchinguserfromSqlite:"+user.toString());
returnuser;
}
/**
*RecratedatabaseDeletealltablesandcreatethemagain
**/
publicvoiddeleteUsers(){
SQLiteDatabasedb=this.getWritableDatabase();
//DeleteAllRows
db.delete(TABLE_USER,null,null);
db.close();
Log.d(TAG,"Deletedalluserinfofromsqlite");
}
activity_login.xml
<?xmlversion="1.0"encoding="utf8"?>
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@color/bg_login"
android:gravity="center"
android:orientation="vertical"
android:padding="10dp">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:orientation="vertical"
android:paddingLeft="20dp"
android:paddingRight="20dp">
<EditText
android:id="@+id/email"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:background="@color/white"
android:hint="@string/hint_email"
android:inputType="textEmailAddress"
android:padding="10dp"
android:singleLine="true"
android:textColor="@color/input_login"
android:textColorHint="@color/input_login_hint"/>
<EditText
android:id="@+id/password"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:background="@color/white"
android:hint="@string/hint_password"
android:inputType="textPassword"
android:padding="10dp"
android:singleLine="true"
android:textColor="@color/input_login"
android:textColorHint="@color/input_login_hint"/>
<!LoginButton>
<Button
android:id="@+id/btnLogin"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dip"
android:background="@color/btn_login_bg"
android:text="@string/btn_login"
android:textColor="@color/btn_login"/>
<!LinktoLoginScreen>
<Button
android:id="@+id/btnLinkToRegisterScreen"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="40dip"
android:background="@null"
android:text="@string/btn_link_to_register"
android:textAllCaps="false"
android:textColor="@color/white"
android:textSize="15dp"/>
</LinearLayout>
</LinearLayout>
LoginActivity.java
/**
*Author:RaviTamada
*URL:www.androidhive.info
*twitter:http://twitter.com/ravitamada
*/
packageinfo.androidhive.loginandregistration.activity;
importandroid.app.Activity;
importandroid.app.ProgressDialog;
importandroid.content.Intent;
importandroid.os.Bundle;
importandroid.util.Log;
importandroid.view.View;
importandroid.widget.Button;
importandroid.widget.EditText;
importandroid.widget.Toast;
importcom.android.volley.Request.Method;
importcom.android.volley.Response;
importcom.android.volley.VolleyError;
importcom.android.volley.toolbox.StringRequest;
importorg.json.JSONException;
importorg.json.JSONObject;
importjava.util.HashMap;
importjava.util.Map;
importinfo.androidhive.loginandregistration.R;
importinfo.androidhive.loginandregistration.app.AppConfig;
importinfo.androidhive.loginandregistration.app.AppController;
importinfo.androidhive.loginandregistration.helper.SQLiteHandler;
importinfo.androidhive.loginandregistration.helper.SessionManager;
publicclassLoginActivityextendsActivity{
privatestaticfinalStringTAG=RegisterActivity.class.getSimpleName();
privateButtonbtnLogin;
privateButtonbtnLinkToRegister;
privateEditTextinputEmail;
privateEditTextinputPassword;
privateProgressDialogpDialog;
privateSessionManagersession;
privateSQLiteHandlerdb;
@Override
publicvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
inputEmail=(EditText)findViewById(R.id.email);
inputPassword=(EditText)findViewById(R.id.password);
btnLogin=(Button)findViewById(R.id.btnLogin);
btnLinkToRegister=(Button)findViewById(R.id.btnLinkToRegisterScreen);
//Progressdialog
pDialog=newProgressDialog(this);
pDialog.setCancelable(false);
//SQLitedatabasehandler
db=newSQLiteHandler(getApplicationContext());
//Sessionmanager
session=newSessionManager(getApplicationContext());
//Checkifuserisalreadyloggedinornot
if(session.isLoggedIn()){
//Userisalreadyloggedin.Takehimtomainactivity
Intentintent=newIntent(LoginActivity.this,MainActivity.
startActivity(intent);
finish();
}
//LoginbuttonClickEvent
btnLogin.setOnClickListener(newView.OnClickListener(){
publicvoidonClick(Viewview){
Stringemail=inputEmail.getText().toString().trim();
Stringpassword=inputPassword.getText().toString().trim();
//Checkforemptydataintheform
if(!email.isEmpty()&&!password.isEmpty()){
//loginuser
checkLogin(email,password);
}else{
//Promptusertoentercredentials
Toast.makeText(getApplicationContext(),
"Pleaseenterthecredentials!",Toast.LENGTH_LONG)
.show();
}
}
});
//LinktoRegisterScreen
btnLinkToRegister.setOnClickListener(newView.OnClickListener(){
publicvoidonClick(Viewview){
Intenti=newIntent(getApplicationContext(),
RegisterActivity.class);
startActivity(i);
finish();
}
});
/**
*functiontoverifylogindetailsinmysqldb
**/
privatevoidcheckLogin(finalStringemail,finalStringpassword){
//Tagusedtocanceltherequest
Stringtag_string_req="req_login";
pDialog.setMessage("Loggingin...");
showDialog();
StringRequeststrReq=newStringRequest(Method.POST,
AppConfig.URL_LOGIN,newResponse.Listener<String>(){
@Override
publicvoidonResponse(Stringresponse){
Log.d(TAG,"LoginResponse:"+response.toString());
hideDialog();
try{
JSONObjectjObj=newJSONObject(response);
booleanerror=jObj.getBoolean("error");
//Checkforerrornodeinjson
if(!error){
//usersuccessfullyloggedin
//Createloginsession
session.setLogin(true);
//NowstoretheuserinSQLite
Stringuid=jObj.getString("uid");
JSONObjectuser=jObj.getJSONObject("user"
Stringname=user.getString("name");
Stringemail=user.getString("email");
Stringcreated_at=user
.getString("created_at");
//Insertingrowinuserstable
db.addUser(name,email,uid,created_at);
//Launchmainactivity
Intentintent=newIntent(LoginActivity.
MainActivity.class);
startActivity(intent);
finish();
}else{
//Errorinlogin.Gettheerrormessage
StringerrorMsg=jObj.getString("error_msg"
Toast.makeText(getApplicationContext(),
errorMsg,Toast.LENGTH_LONG).show();
}
}catch(JSONExceptione){
//JSONerror
e.printStackTrace();
Toast.makeText(getApplicationContext(),"Jsonerror:"
}
}
},newResponse.ErrorListener(){
@Override
publicvoidonErrorResponse(VolleyErrorerror){
Log.e(TAG,"LoginError:"+error.getMessage());
Toast.makeText(getApplicationContext(),
error.getMessage(),Toast.LENGTH_LONG).show();
hideDialog();
}
}){
@Override
protectedMap<String,String>getParams(){
//Postingparameterstologinurl
Map<String,String>params=newHashMap<String,String>();
params.put("email",email);
params.put("password",password);
returnparams;
}
};
//Addingrequesttorequestqueue
AppController.getInstance().addToRequestQueue(strReq,tag_string_req);
}
privatevoidshowDialog(){
if(!pDialog.isShowing())
pDialog.show();
}
privatevoidhideDialog(){
if(pDialog.isShowing())
pDialog.dismiss();
}
}
Now if you run the app, you should see the login screen. But login might not
work as we dont have any user information in mysql database. That can be
done by adding the registration screen.
activity_register.xml
<?xmlversion="1.0"encoding="utf8"?>
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@color/bg_register"
android:gravity="center"
android:orientation="vertical"
android:padding="10dp">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:orientation="vertical"
android:paddingLeft="20dp"
android:paddingRight="20dp">
<EditText
android:id="@+id/name"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:background="@color/input_register_bg"
android:hint="@string/hint_name"
android:padding="10dp"
android:singleLine="true"
android:inputType="textCapWords"
android:textColor="@color/input_register"
android:textColorHint="@color/input_register_hint"
<EditText
android:id="@+id/email"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:background="@color/input_register_bg"
android:hint="@string/hint_email"
android:inputType="textEmailAddress"
android:padding="10dp"
android:singleLine="true"
android:textColor="@color/input_register"
android:textColorHint="@color/input_register_hint"
<EditText
android:id="@+id/password"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:background="@color/input_register_bg"
android:hint="@string/hint_password"
android:inputType="textPassword"
android:padding="10dp"
android:singleLine="true"
android:textColor="@color/input_register"
android:textColorHint="@color/input_register_hint"
<!LoginButton>
<Button
android:id="@+id/btnRegister"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dip"
android:background="#ea4c88"
android:text="@string/btn_register"
android:textColor="@color/white"/>
<!LinktoLoginScreen>
<Button
android:id="@+id/btnLinkToLoginScreen"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="40dip"
android:background="@null"
android:text="@string/btn_link_to_login"
android:textAllCaps="false"
android:textColor="@color/white"
android:textSize="15dp"/>
</LinearLayout>
</LinearLayout>
db. ad dUs er( ) Will insert the user in SQLite database once he is
successfully registered.
RegisterActivity.java
/**
*Author:RaviTamada
*URL:www.androidhive.info
*twitter:http://twitter.com/ravitamada
*/
packageinfo.androidhive.loginandregistration.activity;
importandroid.app.Activity;
importandroid.app.ProgressDialog;
importandroid.content.Intent;
importandroid.os.Bundle;
importandroid.util.Log;
importandroid.view.View;
importandroid.widget.Button;
importandroid.widget.EditText;
importandroid.widget.Toast;
importcom.android.volley.Request.Method;
importcom.android.volley.Response;
importcom.android.volley.VolleyError;
importcom.android.volley.toolbox.StringRequest;
importorg.json.JSONException;
importorg.json.JSONObject;
importjava.util.HashMap;
importjava.util.Map;
importinfo.androidhive.loginandregistration.R;
importinfo.androidhive.loginandregistration.app.AppConfig;
importinfo.androidhive.loginandregistration.app.AppController;
importinfo.androidhive.loginandregistration.helper.SQLiteHandler;
importinfo.androidhive.loginandregistration.helper.SessionManager;
publicclassRegisterActivityextendsActivity{
privatestaticfinalStringTAG=RegisterActivity.class.getSimpleName();
privateButtonbtnRegister;
privateButtonbtnLinkToLogin;
privateEditTextinputFullName;
privateEditTextinputEmail;
privateEditTextinputPassword;
privateProgressDialogpDialog;
privateSessionManagersession;
privateSQLiteHandlerdb;
@Override
publicvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_register);
inputFullName=(EditText)findViewById(R.id.name);
inputEmail=(EditText)findViewById(R.id.email);
inputPassword=(EditText)findViewById(R.id.password);
btnRegister=(Button)findViewById(R.id.btnRegister);
btnLinkToLogin=(Button)findViewById(R.id.btnLinkToLoginScreen);
//Progressdialog
pDialog=newProgressDialog(this);
pDialog.setCancelable(false);
//Sessionmanager
session=newSessionManager(getApplicationContext());
//SQLitedatabasehandler
db=newSQLiteHandler(getApplicationContext());
//Checkifuserisalreadyloggedinornot
if(session.isLoggedIn()){
//Userisalreadyloggedin.Takehimtomainactivity
Intentintent=newIntent(RegisterActivity.this,
MainActivity.class);
startActivity(intent);
finish();
}
//RegisterButtonClickevent
btnRegister.setOnClickListener(newView.OnClickListener(){
publicvoidonClick(Viewview){
Stringname=inputFullName.getText().toString().trim();
Stringemail=inputEmail.getText().toString().trim();
Stringpassword=inputPassword.getText().toString().trim();
if(!name.isEmpty()&&!email.isEmpty()&&!password.isEmpty()){
registerUser(name,email,password);
}else{
Toast.makeText(getApplicationContext(),
"Pleaseenteryourdetails!",Toast.LENGTH_LONG)
.show();
}
}
});
//LinktoLoginScreen
btnLinkToLogin.setOnClickListener(newView.OnClickListener(){
publicvoidonClick(Viewview){
Intenti=newIntent(getApplicationContext(),
LoginActivity.class);
startActivity(i);
finish();
}
});
/**
*FunctiontostoreuserinMySQLdatabasewillpostparams(tag,name,
*email,password)toregisterurl
**/
privatevoidregisterUser(finalStringname,finalStringemail,
finalStringpassword){
//Tagusedtocanceltherequest
Stringtag_string_req="req_register";
pDialog.setMessage("Registering...");
showDialog();
StringRequeststrReq=newStringRequest(Method.POST,
AppConfig.URL_REGISTER,newResponse.Listener<String>(){
@Override
publicvoidonResponse(Stringresponse){
Log.d(TAG,"RegisterResponse:"+response.toString());
hideDialog();
try{
JSONObjectjObj=newJSONObject(response);
booleanerror=jObj.getBoolean("error");
if(!error){
//UsersuccessfullystoredinMySQL
//Nowstoretheuserinsqlite
Stringuid=jObj.getString("uid");
JSONObjectuser=jObj.getJSONObject("user"
Stringname=user.getString("name");
Stringemail=user.getString("email");
Stringcreated_at=user
.getString("created_at");
//Insertingrowinuserstable
db.addUser(name,email,uid,created_at);
Toast.makeText(getApplicationContext(),
//Launchloginactivity
Intentintent=newIntent(
RegisterActivity.this,
LoginActivity.class);
startActivity(intent);
finish();
}else{
//Erroroccurredinregistration.Gettheerror
//message
StringerrorMsg=jObj.getString("error_msg"
Toast.makeText(getApplicationContext(),
errorMsg,Toast.LENGTH_LONG).show();
}
}catch(JSONExceptione){
e.printStackTrace();
}
}
},newResponse.ErrorListener(){
@Override
publicvoidonErrorResponse(VolleyErrorerror){
Log.e(TAG,"RegistrationError:"+error.getMessage());
Toast.makeText(getApplicationContext(),
error.getMessage(),Toast.LENGTH_LONG).show();
hideDialog();
}
}){
@Override
protectedMap<String,String>getParams(){
//Postingparamstoregisterurl
Map<String,String>params=newHashMap<String,String>();
params.put("name",name);
params.put("email",email);
params.put("password",password);
returnparams;
}
};
//Addingrequesttorequestqueue
AppController.getInstance().addToRequestQueue(strReq,tag_string_req);
}
privatevoidshowDialog(){
if(!pDialog.isShowing())
pDialog.show();
}
privatevoidhideDialog(){
if(pDialog.isShowing())
pDialog.dismiss();
}
}
Run the app and navigate to register screen by tapping on the link below login
button.
activity_main.xml
<RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="${relativePackage}.${activityClass}">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:gravity="center"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/welcome"
android:textSize="20dp"/>
<TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:textColor="@color/lbl_name"
android:textSize="24dp"/>
<TextView
android:id="@+id/email"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="13dp"/>
<Button
android:id="@+id/btnLogout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="40dip"
android:background="@color/btn_logut_bg"
android:text="@string/btn_logout"
android:textAllCaps="false"
android:textColor="@color/white"
android:textSize="15dp"/>
</LinearLayout>
</RelativeLayout>
16. Open the MainActivity.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.
MainActivity.java
packageinfo.androidhive.loginandregistration;
importinfo.androidhive.loginandregistration.helper.SQLiteHandler;
importinfo.androidhive.loginandregistration.helper.SessionManager;
importjava.util.HashMap;
importandroid.app.Activity;
importandroid.content.Intent;
importandroid.os.Bundle;
importandroid.view.View;
importandroid.widget.Button;
importandroid.widget.TextView;
publicclassMainActivityextendsActivity{
privateTextViewtxtName;
privateTextViewtxtEmail;
privateButtonbtnLogout;
privateSQLiteHandlerdb;
privateSessionManagersession;
@Override
protectedvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
txtName=(TextView)findViewById(R.id.name);
txtEmail=(TextView)findViewById(R.id.email);
btnLogout=(Button)findViewById(R.id.btnLogout);
//SqLitedatabasehandler
db=newSQLiteHandler(getApplicationContext());
//sessionmanager
session=newSessionManager(getApplicationContext());
if(!session.isLoggedIn()){
logoutUser();
}
//Fetchinguserdetailsfromsqlite
HashMap<String,String>user=db.getUserDetails();
Stringname=user.get("name");
Stringemail=user.get("email");
//Displayingtheuserdetailsonthescreen
txtName.setText(name);
txtEmail.setText(email);
//Logoutbuttonclickevent
btnLogout.setOnClickListener(newView.OnClickListener(){
@Override
publicvoidonClick(Viewv){
logoutUser();
}
});
}
/**
*Loggingouttheuser.WillsetisLoggedInflagtofalseinshared
*preferencesClearstheuserdatafromsqliteuserstable
**/
privatevoidlogoutUser(){
session.setLogin(false);
db.deleteUsers();
//Launchingtheloginactivity
Intentintent=newIntent(MainActivity.this,LoginActivity.
startActivity(intent);
finish();
}
}
Now if you run the app, you should see the below screen after successful login.
Whats Next?
If you understand this article very clearly, its time to improvise your knowledge
by following the below articles.
> Read How to create REST API for Android app using PHP, Slim and MySQL to
learn how to develop a proper REST API for your android app.
> Android Hosting PHP, MySQL RESTful services to DigitalOcean explains how to
deploy your REST services online. So that the urls will be accessible globally.
Change Log
Updated On
ravi8x
Ravi is hardcore Android programmer and Android
programming has been his passion since he compiled his rst
hello-world program. Solving real problems of Android
developers through tutorials has always been interesting part for him.
RELATED POSTS
Android Building
Free Wallpapers
App Part 1
Android JSON
parsing using
Volley
Android working
with Volley
Library
by Ravi Tamada
by Ravi Tamada
by Ravi Tamada
Android
Uploading
Camera Image,
Video to Server
with Progress
Bar
by Ravi Tamada
3479Comments
Recommend 132
AndroidHive
Share
Login
SortbyNewest
Jointhediscussion
SaloniGargadayago
Whatistheuseofsqlitewhenweareusingdatabaseinxampp?
Reply Share
DeepakMani2daysago
Fatalerror:Calltoamemberfunctionprepare()onnullin....functions.php
gettingerrorwheni'mtryingtopassvaluesthroughpostman....plzhelp
Reply Share
DeepakMani2daysago
Fatalerror:Calltoamemberfunctionprepare()onnull.........infunctions.php
wheni'mpassingthevaluesthroughpostman.......
anybodyplzhelp....
Reply Share
knikaha3daysago
itriedtodownloadingprojectfileswithnoluck..Thissitecantbereached
Plzhelp
Reply Share
RaviTamada
plstrynow!
Reply Share
ShanmugamR5daysago
nicetutorialthanksfriend
Reply Share
khaledahmed6daysago
itestconnectionbyPostmananditgivesmeanerror"
{"error":true,"error_msg":"Requiredparameters(name,emailorpassword)is
missing!"}"
alsoiamsendingtheexactrequiredparameterwhatshouldido!
Reply Share
jrdev761>khaledahmed5daysago
whatemulatorareyouusing,androidorgenymotion,
Reply Share
RaviTamada
Areyousureyouarepostingtheparameters?name,emailand
password.
Reply Share
khaledahmed>RaviTamada6daysago
yes,andwhenitestingitfromandroiddevicegetting403
statuscodeiamsureiamclosingfirewallandchangingipto
mine
Reply Share
HabibOlou7daysago
Hello,iamgettinganerror:
Fatalerror:Calltoundefinedmethodmysqli_stmt::get_result()in
/include/DB_Functions.php
atthisline:$user=$stmt>get_result()>fetch_assoc()
Reply Share
ChillyVids7daysago
HiguysmyregistrationworksperfektbutwhenItrytologinIgetthe
followingerror:
Calltoundefinedmethodmysqli_stmt::get_result()
HowcanIfixthisproblem?
Reply Share
HabibOlou>ChillyVids6daysago
Hello,iamhavingthesameproblem.Wereyouabletosolveit?
Reply Share
jrdev761>HabibOlou6daysago
sameproblembutworksperfectwhenworkingusingwampor
localdatabase
Reply Share
RaviTamada
Whichhostingyouaretryingon?
Reply Share
jrdev761>RaviTamada6daysago
IamusingNameCheapserver,whichrunsonCpanel
Reply Share
RaviTamada
Youneedtoenablemysqlisupport.
Reply Share
jrdev761>RaviTamada6daysago
Ihaveenableditalready
Reply Share
RaviTamada
Theremightbeanotherproblem.Checkthelogs.
Reply Share
jrdev761>RaviTamada5daysago
fromtheAndroidStudio:
BasicNetwork.performRequest:Unexpectedresponse
code500forhttp://www......./login_api/login.php
LoginError:null
PhpLog:
PHPFatalerror:Calltoundefinedmethod
mysqli_stmt::get_result()in
............/blwnewmedia/login_api/include/DB_Functions.php
online65
Reply Share
jrdev761>jrdev7615daysago
Actually,Ihavebeenabletosolvethisissue,Iwas
usingbind_resultinsteadofusingget_result,please
refertohttp://stackoverflow.com/quest...
//checkforsuccessfulstore
if($result){
$stmt=$this>conn>prepare("SELECT*FROM
usersWHEREemail=?")
$stmt>bind_param("s",$email)
$stmt>execute()
$user=$stmt>bind_result()>fetch_assoc()
$stmt>close()
return$user
}else{
returnfalse
}
Reply Share
AndreKeren7daysago
howificanmakeamuchfieldformforregistration?
Ex:Name,Address,City,ZipCodeandmanythanks
Reply Share
yoyo9daysago
importinfo.androidhive.loginandregistration.R
HowtomakeandimportR?
Reply Share
jrdev761>yoyo5daysago
youmightwanttotrytocleanandrebuildproject
Reply Share
HaqnawazGul16daysago
Hi:iamjustWannaknow...howcancreatevoicecalloptionsamelike
Reply Share
AbimelecReyes17daysago
Modifytwocanmakethecode
Reply Share
SunithaBist20daysago
ActuallyI'mtryingtorunwithanotherserver..soIftrytoaccess
http://itzmee.net23.net/androi.....imnotgettinganyjsonservicesinsteadof
thatimgettingtheseerrormessages.
.Fatalerror:require_once()[function.require]:Failedopeningrequired
'include/DB_Functions.php'(include_path='.:/usr/lib/php:/usr/local/lib/php')in
/home/a7622610/public_html/android_login_api/register.phponline3
itzmee.net23.netismyservername
Reply Share
SunithaBist20daysago
HiSir!!Imgettingthiserrorwhilecompilingtheregister.php..plzztrytohelp
me
Fatalerror:require_once()[function.require]:Failedopeningrequired
'/home/a7622610/public_html/include/DB_Functions.php'
(include_path='.:/usr/lib/php:/usr/local/lib/php')in
/home/a7622610/public_html/register.phponline3
Reply Share
shashipatil>SunithaBist16daysago
checkthegivenpath
Reply Share
JohnAlexisLagmay22daysago
FATALEXCEPTION:main
java.lang.NullPointerException
at
ph.com.aprox.aprox.activity.RegisterActivity.registerUser(RegisterActivity.java
at
ph.com.aprox.aprox.activity.RegisterActivity.access$300(RegisterActivity.java
at
ph.com.aprox.aprox.activity.RegisterActivity$1.onClick(RegisterActivity.java:79)
atandroid.view.View.performClick(View.java:4240)
atandroid.view.View$PerformClick.run(View.java:17721)
atandroid.os.Handler.handleCallback(Handler.java:730)
atandroid.os.Handler.dispatchMessage(Handler.java:92)
atandroid.os.Looper.loop(Looper.java:137)
atandroid.app.ActivityThread.main(ActivityThread.java:5103)
atjava.lang.reflect.Method.invokeNative(NativeMethod)
atjava.lang.reflect.Method.invoke(Method.java:525)
at
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
atcom.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
atdalvik.system.NativeStart.main(NativeMethod)
IkeepongettingthiserrormessagewheneverIclickregisterbutton
Reply Share
KaranBrahmaxatriya>JohnAlexisLagmay4daysago
sameerrorigotplshelpmeout
Reply Share
AdelAbdallah23daysago
clearandamazing
Reply Share
RaviTamada
:)
Reply Share
KaranBrahmaxatriya>RaviTamada4daysago
FATALEXCEPTION:main
java.lang.NullPointerException
at
com.example.karanbrahmaxatriya.loginandregister.activity.RegisterActivity.registerUser(
at
com.example.karanbrahmaxatriya.loginandregister.activity.RegisterActivity.access$300(
at
com.example.karanbrahmaxatriya.loginandregister.activity.RegisterActivity$1.onClick(
atandroid.view.View.performClick(View.java:3528)
atandroid.view.View$PerformClick.run(View.java:14235)
atandroid.os.Handler.handleCallback(Handler.java:605)
atandroid.os.Handler.dispatchMessage(Handler.java:92)
atandroid.os.Looper.loop(Looper.java:137)
atandroid.app.ActivityThread.main(ActivityThread.java:4424)
atjava.lang.reflect.Method.invokeNative(NativeMethod)
atjava.lang.reflect.Method.invoke(Method.java:511)
at
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java
at
com.android.internal.os.ZygoteInit.main(ZygoteInit.java:584)
atdalvik.system.NativeStart.main(NativeMethod)
Reply Share
KaranBrahmaxatriya>RaviTamada4daysago
sameerrorifacingplshelpme
Reply Share
BurhanCR24daysago
ravisiri'mgettingthis"Unknownerroroccurredinregistration!"
whatmightbetheproblem?
Reply Share
RaviTamada
TryhittingtheurlusingChromePostmanextensionandseeifthere
areanyphperrors.
Reply Share
BurhanCR>RaviTamada24daysago
usingthepostmanextensionitsays"Requiredparameters
(name,year,branch,rollno,emailorpassword)ismissing!"
//hereiswhatichangedinthecode
publicfunctionstoreUser($name,$year,$branch,$rollno,
$email,$password){
$uuid=uniqid('',true)
$hash=$this>hashSSHA($password)
$encrypted_password=$hash["encrypted"]//encrypted
password
$salt=$hash["salt"]//salt
$stmt=$this>conn>prepare("INSERTINTO
studentdata(uniqueid,name,year,branch,rollno,email,
password,salt,createdat)VALUES(?,?,?,?,?,?,?,?,
NOW())")
$stmt>bind_param("ssssssss",$uuid,$name,$year,
$branch,$rollno,$email,$encrypted_password,$salt)
$result=$stmt>execute()
seemore
Reply Share
BurhanCR>BurhanCR24daysago
andwhileusingandroidstudioitgivesmethefollowing
error"Unknownerroroccurredinregistration!"
Reply Share
BurhanCR>BurhanCR22daysago
ravisiranyhelpplease
Reply Share
RaviTamada
SendrequesttologinandregistrationfromChrome
Postmanextensionandseeiftheyareworkingornot.
Reply Share
Chinemerem25daysago
HiraviItriedtocomplileyourexampebutitgivesmethefollowingerrorson
LoginandRegisterActivity
MethodonErrorResponsedoesnotoverridemethodfromitssuperclass
MethodonResponsedoesnotoverridemethodfromitssuperclass
Thereisnoapplicableconstructorto'(int,java.lang.string,
info.androidhive.loginandregisration.activity.registerActivity.(anonymous),
info.androidhive.loginandregistration.activity.registerActivity.(anonymous))'
Reply Share
RaviTamada
Canupastethecompletecodeblockwhichiscausingerror.
Reply Share
ImmaculataUbahamonthago
ThankyouRaviforthistutorial.Ithelpedgettingmestarted.
ikeptrunningintonullpointererrorwheniclickontheregisterbutton."
java.lang.NullPointerException
at
com.applications.inma.smartstudy.activity.RegisterActivity.registerUser(RegisterActivity.java
at
com.applications.inma.smartstudy.activity.RegisterActivity.access$300(RegisterActivity.java
at
com.applications.inma.smartstudy.activity.RegisterActivity$1.onClick(RegisterActivity.java
atandroid.view.View.performClick(View.java:4438)
atandroid.view.View$PerformClick.run(View.java:18422)
atandroid.os.Handler.handleCallback(Handler.java:733)
atandroid.os.Handler.dispatchMessage(Handler.java:95)
atandroid.os.Looper.loop(Looper.java:136)
atandroid.app.ActivityThread.main(ActivityThread.java:5001)
atjava.lang.reflect.Method.invokeNative(NativeMethod)
atjava.lang.reflect.Method.invoke(Method.java:515)
at
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
atcom.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
atdalvik.system.NativeStart.main(NativeMethod)"
Howdoiresolvethis?
Thanks
Reply Share
NickyN>ImmaculataUbah24daysago
ifyoushowedthecodewhichhasexception...
Mostlyyoushouldcheckifyouhavedefinedthebutton
(findviewbyid..)andyoudefinedthecorrectone
Reply Share
ImmaculataUbah>NickyN22daysago
Thanks.Ihaveresolvedit
Reply Share
KaranBrahmaxatriya>ImmaculataUbah
4daysago
howuresolvedit?
Reply Share
qweqwe>ImmaculataUbah25daysago
diduaddedAppControllerinAndroidManifest?
QUICK CONTACT
ABOUT ANDROIDHIVE
Advertise with us
AndroidHive is beginner's
Privacy Policy
Terms of Service
Sitemap