In this android tutorial, we are going to learn how we can implement android user login and registration with retrofit, Php, MySql and Slim framework. This topic might sound as if a lot is going on but if you follow the tutorial to the end you will learn how you can combine different technologies to achieve your aim.
Retrofit is a type-safe REST client for Android built by Square. The library provides a powerful framework for authenticating and interacting with APIs and sending network requests with OkHttp.
This library makes downloading JSON or XML data from a web API fairly straightforward. Once the data is downloaded then it is parsed into a Plain Old Java Object (POJO) which must be defined for each “resource” in the response.
We are going to create an android user login and registration. We will create an API endpoints which our android client application will make call to and use the response data received to execute further actions.
I wrote initial android tutorial on Android User Login and Registration. I will suggest you have a look at it before you continue with this tutorial.
We are going to consume our user registration data using android retrofit library. Retrofit is one of the best android library for network applications.
If you are interested in android OkHttp library tutorial, I wrote the following tutorial on ANDROID PUSH NOTIFICATIONS USING GOOGLE CLOUD MESSAGING (GCM), PHP, MYSQL AND OKHTTP and I think it will interest you.
Right now it is important for us to understand what we are planning to achieve in this tutorial. The screen-shot of our project is shown below.
We will create a simple database that will contain a single table called user. The user table will contain user registration information. If you don’t have a remote database server you can as well use a local server like WAMP. The sql code below will create the user table in our database.
CREATE TABLE IF NOT EXISTS `user` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `email` varchar(300) DEFAULT NULL, `password` varchar(300) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=0 ;
Database Connect with web server application
Now, we are going to connect our web application to our database server so that the information stored in the database can be access in the web application.
Create your application root folder called api for our web application. Inside the api root folder, create a configuration file called config.php. Copy and paste the below code inside the file. Don’t forget to enter your database server access details
config.php
<?php define("DB_HOST", " "); define("DB_USER", " "); define("DB_PASSWORD", " "); define("DB_NAME", " "); ?>
Create another file called db.php which will return the instance of our database.
db.php
<?php include_once 'config.php'; class DbConnect{ private $connect; public function __construct(){ $this->connect = mysqli_connect(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME); if (mysqli_connect_errno($this->connect)) { echo "Failed to connect to MySQL: " . mysqli_connect_error(); } } public function getDb(){ return $this->connect; } } ?>
We are going to create a separate class that will contain the methods we will use in our REST API. Create a file called database.php. Copy and paste the below code in this file.
Database.php
<?php include_once 'db.php'; class DatabaseLayer{ public function __constructor(){ } public function isUserExist($email, $password){ $dbObject = new DbConnect(); $sql = "Select * from user where email = $email and password = $password limit 1"; $result = mysqli_query($dbObject->getDb(), $sql); if(count($result) > 0){ return true; } return false; } public function addNewUser($email, $password){ $dbObject = new DbConnect(); if(!$this->isUserExist($email, $password)){ $sql = "Insert into user (email, password) values ('$email', '$password')"; $result = mysqli_query($dbObject->getDb(), $sql); if($result){ return true; } return false; } } } ?>
Creating Web API with Slim 2 Php Framework
Instead of writing our own API from scratch, it is better for us to use a well tested open source Php framework that basically do what we planned to achieve.
If you have not heard of Php Slim framework, you can read more here. Slim is a PHP micro framework that helps you quickly write simple yet powerful web applications and APIs.
To install and use this framework, you can just download it in their website and following the installation instruction or you can install Slim with Composer. If you don’t have Composer installed in your system, you can head over to getcomposer.org to download and follow the installation instruction.
Create a new file in the root directory called composer.json and add the following lines of code.
Composer.json
{ "require": { "slim/slim": "2.*" } }
Open you command line application as an administrator and execute the following line of code.
Composer install
We will create a new index.php file in the root directory of our project. Add the following line of code to it first.
require ‘vendor/autoload.php‘
The downloaded Slim framework is added inside a new created folder called vendor. The vendor folder is where Composer store all the dependency modules used in the project.
We are going to create two endpoints for our API. For example.
GET – http://localhost/api/email/password. For login process
POST – http://localhost/api/email/password. For registration process
Create the index.php file. Copy and paste below code in the file.
Index.php
<?php require 'vendor/autoload.php'; include_once 'database.php'; $app = new SlimSlim(); $app->get('/:email/:password', function($email, $password){ $password = md5($password); $databaseObject = new DatabaseLayer(); $isRegistered = $databaseObject->isUserExist($email, $password); $app = SlimSlim::getInstance(); if($isRegistered){ $app->response->setStatus('200'); $app->response->headers->set('Content_Type', 'application/json'); echo json_encode(Array('isLogin' => '1')); }else{ echo json_encode(Array('isLogin' => '0')); } }); $app->post('/:email/:password', function($email, $password){ $password = md5($password); $app = SlimSlim::getInstance(); $databaseObject = new DatabaseLayer(); $isInserted = $databaseObject->addNewUser($email, $password); if($isInserted){ $app->response->setStatus('200'); $app->response->headers->set('Content_Type', 'application/json'); echo json_encode(Array('isLogin' => '1')); }else{ echo json_encode(Array('isLogin' => '0')); } }); $app->run(); ?>
You can see the two functions above, one for the GET request and the other for the POST request.
We can test our GET request directly in the browser by passing the parameters to the base url pointing to our API.
For the POST request, you can download a Google Chrome extension call Chrome Poster which allow you to interact with your web server.
It is time to move over to the android client app. We are going to creating android application that will consume our web API and used it for user registration and login.
Android Client App
Before we start, it is important for you to understand the tools and environment I used in this android tutorial. Feel free to use tools you are familiar with.
Windows 7
Android Studio
Sony Xperia ZL
Min SDK 14
Target SDK 23
To create a new android application project, following the steps as stipulated below.
Go to File menu
Click on New menu
Click on Android Application
Enter Project name: AndroidUserLoginWithRetrofit
Package: com.inducesmile.androiduserloginwithretrofit
Select Login Activity
Keep other default selections
Continue to click on next button until Finish button is active, then click on Finish Button.
If you are using Android Studio as your choice IDE, the new project will create a default
LoginActivity.java file and its corresponding layout file.
Since we are going to use android retrofit library for our network call, open the app build.gradle and add the following lines of code to the dependency section.
dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) testCompile 'junit:junit:4.12' compile 'com.android.support:appcompat-v7:23.1.1' compile 'com.android.support:design:23.1.1' compile 'com.google.code.gson:gson:2.6.1' compile 'com.squareup.retrofit2:retrofit:2.0.0-beta4' compile 'com.squareup.retrofit2:converter-gson:2.0.0-beta4' compile 'com.squareup.okhttp3:okhttp:3.1.2' }
You can see that apart from retrofit, we also add OkHttp and Gson libraries. Retrofit is built on top of OkHttp. The Gson library is use as a converter factory to serialize and deserialize JSON data
Since retrofit 2, the following converter can be used also
Jackson – com.squareup.retrofit2:converter-jackson:2.0.0-beta4
Moshi – com.squareup.retrofit2:converter-moshi:2.0.0-beta4
Protobuf – com.squareup.retrofit2:converter-protobuf:2.0.0-beta4
Wire – com.squareup.retrofit2:converter-wire:2.0.0-beta4
Simple XML – com.squareup.retrofit2:converter-simplexml:2.0.0-beta4
Mainfest.xml
Since we are making a network call, we are going to add Internet permission in our application Manifest.xml file.
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.inducesmile.androidloginwithretrofit"> <uses-permission android:name="android.permission.INTERNET" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".LoginActivity" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".MainActivity"></activity> </application> </manifest>
Colors.xml
Open the colors.xml file located in the values folder and add these lines of code.
<?xml version="1.0" encoding="utf-8"?> <resources> <color name="colorPrimary">#3F51B5</color> <color name="colorPrimaryDark">#303F9F</color> <color name="colorAccent">#FF4081</color> <color name="colorBlack">#000000</color> </resources>
Feel free to choose any color you might be interested to use.
Strings.xml
The default and some of the string values we will add in our application are stored in the strings.xml file located in the values folder. Open the file, copy and paste the following code in the file.
<resources> <string name="app_name">Android Login With Retrofit</string> <!-- Strings related to login --> <string name="prompt_email">Email</string> <string name="prompt_password">Password </string> <string name="registration_button">Register</string> <string name="action_sign_in">Sign in</string> <string name="action_sign_in_short">Sign in</string> <string name="error_invalid_email">This email address is invalid</string> <string name="error_invalid_password">This password is too short</string> <string name="error_incorrect_password">This password is incorrect</string> <string name="error_field_required">This field is required</string> <string name="permission_rationale">Contacts permissions are needed for providing email completions.</string> <string name="no_text"> </string> <string name="registration_message">You are not registered yet. Use the registration button to complete your registration.</string> <string name="registration_failed">Your email or password is already in use</string> <string-array name="autocomplete"> <item>johnpaul@yahoo.com</item> <item>marykate@yahoo.com</item> <item>kelvinjames@yahoo.com</item> <item>henrysweart@gmail.com</item> <item>gracepowell@yahoo.com</item> </string-array> </resources>
Lets create the MainActivity.java file. This Activity page will server as the first page a user will see when successfully login. It is going to be simple. The layout file for this Activity will only contain a single TextView control which will display user login email address.
activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns: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" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.inducesmile.androidloginwithretrofit.MainActivity"> <TextView android:id="@+id/login_email" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/app_name" android:textColor="@color/colorBlack" android:layout_margin="16dp" android:textSize="16dp" android:textStyle="bold" android:gravity="center|center_horizontal" android:layout_centerVertical="true" android:layout_centerHorizontal="true"/> </RelativeLayout>
The MainActivity class will instantiate the TextView control using the findViewById(int k) method of the Activity class. The object of the TextView’s text component is set with the data (User login email address) obtained from the intent extra data as parameter.
Open the MainActivity.java file, copy and paste the code below to the file.
MainActivity.java
import android.content.Intent; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.widget.TextView; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); String myLoginEmailAddress = getLoginEmailAddress(); TextView loginInformation = (TextView)findViewById(R.id.login_email); if(myLoginEmailAddress != null || !myLoginEmailAddress.equals("")){ loginInformation.setText("Welcome!!! You have logged in as " + myLoginEmailAddress); }else { loginInformation.setText("Your login email is missing"); } } private String getLoginEmailAddress(){ String storedEmail = ""; Intent mIntent = getIntent(); Bundle mBundle = mIntent.getExtras(); if(mBundle != null){ storedEmail = mBundle.getString("EMAIL"); } return storedEmail; } }
We will modify the default activity_login.xml file create by Android Studio when we select LoginActivity default template. We are going to add one Button and one TextView controls.
The new Button view will be used for registration while the TextView is used to display login denial message.
Open the activity_login.xml file located in the layout folder. Copy and paste the following code inside this file.
activity_login.xml
<LinearLayout xmlns: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" android:gravity="center_horizontal" android:orientation="vertical" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.inducesmile.androidloginwithretrofit.LoginActivity"> <!-- Login progress --> <ProgressBar android:id="@+id/login_progress" style="?android:attr/progressBarStyleLarge" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="8dp" android:visibility="gone" /> <ScrollView android:id="@+id/login_form" android:layout_width="match_parent" android:layout_height="match_parent" android:scrollbars="none"> <LinearLayout android:id="@+id/email_login_form" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <android.support.design.widget.TextInputLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <AutoCompleteTextView android:id="@+id/email" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="@string/prompt_email" android:inputType="textEmailAddress" android:maxLines="1" android:singleLine="true" /> </android.support.design.widget.TextInputLayout> <android.support.design.widget.TextInputLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <EditText android:id="@+id/password" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="@string/prompt_password" android:imeActionId="@+id/login" android:imeActionLabel="@string/action_sign_in_short" android:imeOptions="actionUnspecified" android:inputType="textPassword" android:maxLines="1" android:singleLine="true" /> </android.support.design.widget.TextInputLayout> <Button android:id="@+id/email_sign_in_button" style="?android:textAppearanceSmall" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="16dp" android:text="@string/action_sign_in" android:textColor="@color/colorBlack" android:textStyle="bold" /> <Button android:id="@+id/registration_button" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="16dp" android:text="@string/registration_button" android:textColor="@color/colorBlack" android:textStyle="bold"/> <TextView android:id="@+id/failed_login" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="@color/colorPrimaryDark" android:layout_margin="24dp" android:textSize="16sp" android:text="@string/no_text"/> </LinearLayout> </ScrollView> </LinearLayout>
Before we open the LoginActivity.java, it is important for us to understand how we are going to setup the android retrofit library. For a thorough understanding of what retrofit is all about I will suggest you read their GitHub webpage.
We are going to create our APIService. This is use to create annotation of the query string which is used for the remote call.
Understanding how to map your URL with the corresponding API endpoints is the challenging part of learning android retrofit.
We will create an Interface file in our project called ApiInterface.java.
ApiInterface.java
Open the file, copy and paste the following code in the file.
import retrofit2.Call; import retrofit2.http.GET; import retrofit2.http.POST; import retrofit2.http.Path; public interface ApiInterface { @GET("api/{email}/{password}") Call<Login> authenticate(@Path("email") String email, @Path("password") String password); @POST("api/{email}/{password}") Call<Login> registration(@Path("email") String email, @Path("password") String password); }
As you can see, we are using the GET request annotation with parameters we are going to pass to the base URL of the web API we are planning to access. You can find more information about this annotation in the guide I referenced above.
Finally, lets move over to the LoginActivity class to understand how we can tie all these together and achieve our purpose.
I have created this method below.
private ApiInterface getInterfaceService() { Retrofit retrofit = new Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .build(); final ApiInterface mInterfaceService = retrofit.create(ApiInterface.class); return mInterfaceService; }
An instance of retrofit object was built and thereafter, we use this object to create a service by pass our ApiInterface class as a parameter to retrofit create method.
The returned service object is then use to call any of the methods declared in the ApiInterface.java file
Since you can use retrofit for both asynchronous and synchronous call, we will focus on asynchronous call since the response object will be used to update some of our UI View controls.
We will call the enqueue() method which uses a callback class and override methods for the response object and on failure error message.
The complete code for the LoginActivity.java file is shown below.
LoginActivity.java
import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.annotation.TargetApi; import android.content.Intent; import android.os.Build; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.text.TextUtils; import android.view.KeyEvent; import android.view.View; import android.view.View.OnClickListener; import android.view.inputmethod.EditorInfo; import android.widget.ArrayAdapter; import android.widget.AutoCompleteTextView; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; import retrofit2.Call; import retrofit2.Callback; import retrofit2.Response; import retrofit2.Retrofit; import retrofit2.converter.gson.GsonConverterFactory; /** * A login screen that offers login via email/password. */ public class LoginActivity extends AppCompatActivity { private final String TAG = "LoginActivity"; public static final String BASE_URL = "http://nigerianstudentshop.com/"; // UI references. private AutoCompleteTextView mEmailView; private EditText mPasswordView; private View mProgressView; private View mLoginFormView; private TextView failedLoginMessage; View focusView = null; private String email; private String password; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_login); // Set up the login form. mEmailView = (AutoCompleteTextView) findViewById(R.id.email); populateAutoComplete(); failedLoginMessage = (TextView)findViewById(R.id.failed_login); mPasswordView = (EditText) findViewById(R.id.password); mPasswordView.setOnEditorActionListener(new TextView.OnEditorActionListener() { @Override public boolean onEditorAction(TextView textView, int id, KeyEvent keyEvent) { if (id == R.id.login || id == EditorInfo.IME_NULL) { attemptLogin(); return true; } return false; } }); Button mEmailSignInButton = (Button) findViewById(R.id.email_sign_in_button); mEmailSignInButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { failedLoginMessage.setText(""); attemptLogin(); } }); Button registrationButton = (Button)findViewById(R.id.registration_button); registrationButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { attemptRegistration(); } }); mLoginFormView = findViewById(R.id.login_form); mProgressView = findViewById(R.id.login_progress); } private void attemptRegistration(){ boolean mCancel = this.loginValidation(); if (mCancel) { focusView.requestFocus(); } else { registrationProcessWithRetrofit(email, password); } } private void attemptLogin(){ boolean mCancel = this.loginValidation(); if (mCancel) { focusView.requestFocus(); } else { loginProcessWithRetrofit(email, password); } } private boolean loginValidation() { // Reset errors. mEmailView.setError(null); mPasswordView.setError(null); // Store values at the time of the login attempt. email = mEmailView.getText().toString(); password = mPasswordView.getText().toString(); boolean cancel = false; // Check for a valid password, if the user entered one. if (!TextUtils.isEmpty(password) && !isPasswordValid(password)) { mPasswordView.setError(getString(R.string.error_invalid_password)); focusView = mPasswordView; cancel = true; } // Check for a valid email address. if (TextUtils.isEmpty(email)) { mEmailView.setError(getString(R.string.error_field_required)); focusView = mEmailView; cancel = true; } else if (!isEmailValid(email)) { mEmailView.setError(getString(R.string.error_invalid_email)); focusView = mEmailView; cancel = true; } return cancel; } private void populateAutoComplete(){ String[] countries = getResources().getStringArray(R.array.autocomplete); ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,countries); mEmailView.setAdapter(adapter); } private boolean isEmailValid(String email) { //TODO: Replace this with your own logic return email.contains("@"); } private boolean isPasswordValid(String password) { //TODO: Replace this with your own logic return password.length() > 4; } /** * Shows the progress UI and hides the login form. */ @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2) private void showProgress(final boolean show) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) { int shortAnimTime = getResources().getInteger(android.R.integer.config_shortAnimTime); mLoginFormView.setVisibility(show ? View.GONE : View.VISIBLE); mLoginFormView.animate().setDuration(shortAnimTime).alpha(show ? 0 : 1).setListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { mLoginFormView.setVisibility(show ? View.GONE : View.VISIBLE); } }); mProgressView.setVisibility(show ? View.VISIBLE : View.GONE); mProgressView.animate().setDuration(shortAnimTime).alpha( show ? 1 : 0).setListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { mProgressView.setVisibility(show ? View.VISIBLE : View.GONE); } }); } else { mProgressView.setVisibility(show ? View.VISIBLE : View.GONE); mLoginFormView.setVisibility(show ? View.GONE : View.VISIBLE); } } private ApiInterface getInterfaceService() { Retrofit retrofit = new Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .build(); final ApiInterface mInterfaceService = retrofit.create(ApiInterface.class); return mInterfaceService; } private void loginProcessWithRetrofit(final String email, String password){ ApiInterface mApiService = this.getInterfaceService(); Call<Login> mService = mApiService.authenticate(email, password); mService.enqueue(new Callback<Login>() { @Override public void onResponse(Call<Login> call, Response<Login> response) { Login mLoginObject = response.body(); String returnedResponse = mLoginObject.isLogin; Toast.makeText(LoginActivity.this, "Returned " + returnedResponse, Toast.LENGTH_LONG).show(); //showProgress(false); if(returnedResponse.trim().equals("1")){ // redirect to Main Activity page Intent loginIntent = new Intent(LoginActivity.this, MainActivity.class); loginIntent.putExtra("EMAIL", email); startActivity(loginIntent); } if(returnedResponse.trim().equals("0")){ // use the registration button to register failedLoginMessage.setText(getResources().getString(R.string.registration_message)); mPasswordView.requestFocus(); } } @Override public void onFailure(Call<Login> call, Throwable t) { call.cancel(); Toast.makeText(LoginActivity.this, "Please check your network connection and internet permission", Toast.LENGTH_LONG).show(); } }); } private void registrationProcessWithRetrofit(final String email, String password){ ApiInterface mApiService = this.getInterfaceService(); Call<Login> mService = mApiService.registration(email, password); mService.enqueue(new Callback<Login>() { @Override public void onResponse(Call<Login> call, Response<Login> response) { Login mLoginObject = response.body(); String returnedResponse = mLoginObject.isLogin; //showProgress(false); if(returnedResponse.trim().equals("1")){ // redirect to Main Activity page Intent loginIntent = new Intent(LoginActivity.this, MainActivity.class); loginIntent.putExtra("EMAIL", email); startActivity(loginIntent); } if(returnedResponse.trim().equals("0")){ // use the registration button to register failedLoginMessage.setText(getResources().getString(R.string.registration_failed)); mPasswordView.requestFocus(); } } @Override public void onFailure(Call<Login> call, Throwable t) { call.cancel(); Toast.makeText(LoginActivity.this, "Please check your network connection and internet permission", Toast.LENGTH_LONG).show(); } }); } }
Login Class
Create a new java file called Login.java. Open the class and add the code below to it
public class Login { public String isLogin; }
This brings us to the end of this tutorial, If you find anything confusing kindly contact me with your questions or use the comment box below.
Now, when you run your application you will see the interface that looks similar to the sample that was shown earlier on.
You can download the code for this tutorial below. If you are having hard time downloading the tutorials, kindly contact me.
Remember to subscribe with your email address so that you will be among the first to receive my new post once it is published.
You are having a java.lang.NullPointerException error in your onResponse method. Probably, nothing is return from your server. Please check if you are returning anything from your server.
thanks for the tutorial… i’m new to android and java.
I got error ‘Cannot resolve symbol ‘Login” in my LoginActivity. how to solve this problem? thanks again.
Can you show me the line of code that throws this error?
Error:(14, 10) error: cannot find symbol class Login
Your app throws a nullpointerexception because of the empty Login class
The login class is as shown below. It is very simple
public class Login {
public String isLogin;
}
Sorry, my own fault. I didn’t direct the app to my root folder.
No worries. Glad it is working for you.
Sorry, but I have one last question though.
I don’t understand what, exactly these lines of code reference to, considering there is no ’email’ or ‘password’ directory or file.
$app->post(‘/:email/:password’, function($email, $password){
$password = md5($password);
GET – http://localhost/api/email/password. For login process
POST – http://localhost/api/email/password. For registration process
Where exactly are we POSTing or GETting from?
If you look at the APIInterface.java class, you will see something like this @POST(“api/{email}/{password}”). It signifies that we are post email and password to server side
So on the server side, we are getting the content of the post variables with the server post request
$app->post(‘/:email/:password’, function($email, $password)
/:email/:password represents the variables while $email and $password represent their values.
Hope it makes sense to you.
i got this error message, anybody can help me please ?
Fatal error: Class ‘SlimSlim’ not found in C:\xampp\htdocs\phpserverside\index.php on line 5
@owin, are you using Slim Php Framework or just index.php in your local web server?
Hello Henry. I’ve just installed this app and trying to test it. So far, when it starts running all I get is the view with ‘Welcome!!! You have logged in as’, which comes from the Main_Activity.java module. How is it suppose to start-up? I would expect to have to register first, then logon, before getting this view.
After I get this working, I want to talk to you about your code services, to help me develop and learn how to create an app idea for Android and iOS. So, I look forward to working on this and more.
Thanks.
Hello, you can uninstall the app and install a fresh copy. Why this happened is because the login details have already been saved in Shared Preference. You can as well clear your app data then you will see the login and registration input forms
Get back to me if you have more questions
I’ve uninstalled and reinstalled a fresh copy. I’ve cleared the app data. I’ve tried using code to clear Shared Preferences like the following: PreferenceManager.getDefaultSharedPreferences(getBaseContext()).
edit().clear().commit();
So far, nothing has worked – I’m still getting the same results.
I’m using the Genymotion ADB. Would this make a difference?
Thanks.
Henry very good attempt and thanks for sharing it with us.
I just downloaded your project and run it in my android phone.
The loggin screen appears, but after pressing the “SIGN IN” button the process stops unexpectendly.
For your information, currently i did not prepare the server side scripts and not enable the server.
The error, as expected, is the next
java.lang.IllegalArgumentException: Illegal URL: path to your server
In this case, the “SIGN IN” process should not show a relevant to the case message? How does this configured in the above case?
I am asking because the are case that the server might be down for a couple of reasons. Why does the application to stop running like that?
Thank you.
Sorry for coming back, the same happens even if the wifi connection is switched off.
The message about WiFi connection does not appear.
Thank you.
The link is path to your server and you did not provide it. You can rewrite the code by showing a Toast message when the server url is not provided.
Thank you for your prompt reply.
What about an invalid URL to the server ?
How can i check it in order to display a toast message?
Thank you again.
Also, when the Wifi connection is switched off, why the message you have in your code for onFailure() does not activated ?
Henry ok solved. I placed a “typical” valid URL and check.
The messages are shown correct.
I will proceed with the next step to create the server side and if there is any problem i will get back to you for assistance.
Thanks a lot for your support.
Great you find a solution. I am always here.
Henry a question with Slim Framework.
I just installed the 3.0 version and after running the index.php, it returns an error at the line –> $app = new SlimSlim();
I just see that in 3.0 version this might changed to the next
$app = new \Slim\App;
but this did not fix the problem.
Could you please assist me?
Thank you.
So, to add more value to your work, in Slim FrameWork Ver 3.0 the below statement
$app = new SlimSlim();
should be replaced with the next one
$app = new \Slim\App();
Therefore many other seems to be also changed!!!
For instance $app = SlimSlim::getInstance(); is no longer exists.
Is there any idea on that?
I used Slim 2 php frameworrk in this project but in my latest projects I used Slim 3 which is the current version. You can see one of the examples here https://inducesmile.com/android/android-news-app-with-admin-panel-in-php-and-mysql/. Although it is not a free app.
Please update the Slim 2 to Slim 3 and everything will work out for you if you want to use Slim 3 but Slim 2 is works. Do let me know if you have more questions
Is there any suggestion on replacing the next
$app = SlimSlim::getInstance();
with other in Ver3?
OK it seems that it is not so easy to change to Ver3.0.
So, i installed ver2.0 of slim framework.
Prepared the database, started the Apache server but still craching my app on android.
I do not now what else to check!!
Could you please tell me where “api” is located and what it should contain
@GET(“api/{email}/{password}”)
Thank you.
api is the root web app folder. Inside the web app root folder, there is an index.php file.
The email and password are value you pass from your android app to the index.php file inside the api folder.
Hope it makes sense to you.
Thanks for handling all my questions.
When trying to run an error returns that Slimlim i uknown !
$app = new SlimSlim();
Could you please advice what is SlimSlim ? Do i have to write Slim/Slim instead?
Thank you.
Also, BASE_URL what exactly must contain?
e.g. “http://localhost/”
Is the above correct when i want to run in local machine ?
“http://localhost/api” should be the path to your web server app
im getting a network error, what should i pass in the url ???
You will pass the url or path that points to your web application.
Can you provide the server side code using Java rather than Php?
I will do that when time permits. Thanks
Thank you Henry, I setup and able to run the client side app and Can you explain step by step process where to deploy the server side PHP project we have downloaded in the Zip and what is the exact URL we need to mention it in the android app. Thank you.
i’m unable to get registered.. it always executing onFailure()….. what’s the reason???
When I run the app it always show the message “Please check your network connection and internet permission”. I did not find any reason. Could you please help me in this regard?
Also the full url is “http://api.test.com/api/email/password” as I kept all php server side code inside folder “api”. So, base url will be “http://api.test.com/api/” am I correct?
Are you using POST or GET Method?
Hi, I just downloaded your source code and try to run at “http://localhost:8080/api” but the response is always 404 Not found. Please help me.
Hi Great tutorial,you have any tutorials for broadcast receivers to check internet connection in the entire application.
Thanks for your great tutrial i have used it but i have aproblem i don’t know where is the problem is it with my own api or what even i tested my api on postman it works fine please can you tested it and tell me the result if the error is from my api or where this my own one where is user name or password is error it returned cloumn1 as your islogin return 0
http://rushsafety.com/webapi/api/Emp/GetEmployee?Uemail=ds.coms@sd.com&Upassword=12345678
and thid is the result
[
{
“Column1”: 0
}
]
and i have made debug i get the error in
URL query string “%s” must not have replace block. For dynamic query parameters use @Query. andriod problem
i have changed it to use @Query parameter instead of @path but no way can you help me to know where is the error i use mvc api c# . thanks