In the 1st part of this article we have learned how to create the required REST API for this app. In this part we are going to see how to build the android app that interact with the API to receive the SMS and get it verified. As this project uses volley to make http calls, I suggest you go through my Volley tutorial to know the usage of volley. Also you need to have basic knowledge on android services and broadcast receivers.

We are going to use SMS broadcast receiver to read the sms whenever device receives it and an Intent Service to make the http calls which sends the OTP to server to get it verified.

android-sms-verification-like-whatsapp

Below is the screenshot of the app we are going to build now.

android-sms-verification-like-whatsapp-viber-2

6. Creating the Android App

This app contains two activities. One with a ViewPager with two pages. One page is to enter the mobile number and other page is to enter the OTP. The second activity is to display the logged in user profile information.

1. In Android Studio, create a new project by navigating to File ⇒ New Project and fill all the required details. When it prompts to select a default activity, select Blank Activity and proceed.

2. Open build.gradle located under app folder and add volley library dependency by adding com.mcxiaoke.volley:library-aar:1.0.0.

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile "com.android.support:appcompat-v7:22.1.1"
    compile 'com.mcxiaoke.volley:library-aar:1.0.0'
}

6.1 Making the App Material

This step is optional but I recommend you go through it as it improves your knowledge on material design. Follow my Material Design tutorial to get to know how to make your android app material design ready.

3. Open strings.xml located under res ⇒ values and add below string values.

<resources>
    <string name="app_name">SMS Verification</string>

    <string name="hello_world">Hello world!</string>
    <string name="action_settings">Settings</string>
    <string name="title_activity_sms">SmsActivity</string>
    <string name="action_logout">Logout</string>
    <string name="msg_enter_mobile">Enter your mobile number to get started!</string>
    <string name="lbl_name">Name</string>
    <string name="lbl_email">Email</string>
    <string name="lbl_mobile">Mobile</string>
    <string name="lbl_next">NEXT</string>
    <string name="msg_sit_back">Sit back &amp; Relax! while we verify your mobile number</string>
    <string name="msg_manual_otp">(Enter the OTP below in case if we fail to detect the SMS automatically)</string>
    <string name="lbl_enter_otp">Enter OTP</string>
    <string name="lbl_submit">SUBMIT</string>
</resources>

4. Open colors.xml located under res ⇒ values and add below color values.

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorPrimary">#3b5bb3</color>
    <color name="colorPrimaryDark">#303F9F</color>
    <color name="textColorPrimary">#FFFFFF</color>
    <color name="windowBackground">#FFFFFF</color>
    <color name="navigationBarColor">#000000</color>
    <color name="colorAccent">#ea5d88</color>

    <color name="bg_view_sms">#ffd423</color>
    <color name="bg_view_otp">#fc6d38</color>
</resources>

4. Now open styles.xml located under res ⇒ values and add below styles.

<resources>

    <style name="MyMaterialTheme" parent="MyMaterialTheme.Base">

    </style>

    <style name="MyMaterialTheme.Base" parent="Theme.AppCompat.Light.DarkActionBar">
        <item name="windowNoTitle">true</item>
        <item name="windowActionBar">false</item>
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

</resources>

5. Under res directory, create a folder named values-v21. In this folder create another styles.xml and add below code.

<resources>

    <style name="MyMaterialTheme" parent="MyMaterialTheme.Base">
        <item name="android:windowContentTransitions">true</item>
        <item name="android:windowAllowEnterTransitionOverlap">true</item>
        <item name="android:windowAllowReturnTransitionOverlap">true</item>
        <item name="android:windowSharedElementEnterTransition">@android:transition/move</item>
        <item name="android:windowSharedElementExitTransition">@android:transition/move</item>
    </style>

</resources>

7. Finally open the AndroidManifest.xml and add the MyMaterialTheme to <application> tag.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="info.androidhive.smsverification">

    <application
        android:theme="@style/MyMaterialTheme">
        .
        .
    </application>

</manifest>

Now if you run the app, you can see the top notification bar color changed which means the material design theme is applied.

3. Now create five packages named activity, app, helper, receiver and service. These packages helps in keeping the project organized.

Below is screenshot of the final project of this tutorial.

android-sms-verification-project-structure

4. Under app package, create a class named Config.java. This class contains very important app configuration information.

> URL_REQUEST_SMS and URL_VERIFY_OTP should be correct. The ip address should match with your localhost PC.

> SMS_ORIGIN should match the value in your PHP project’s Config.php.

> OTP_DELIMITER should also match the value in your PHP project’s Config.php.

package info.androidhive.smsverification.app;

/**
 * Created by Ravi on 08/07/15.
 */
public class Config {
    // server URL configuration
    public static final String URL_REQUEST_SMS = "http://192.168.0.101/android_sms/msg91/request_sms.php";
    public static final String URL_VERIFY_OTP = "http://192.168.0.101/android_sms/msg91/verify_otp.php";

    // SMS provider identification
    // It should match with your SMS gateway origin
    // You can use  MSGIND, TESTER and ALERTS as sender ID
    // If you want custom sender Id, approve MSG91 to get one
    public static final String SMS_ORIGIN = "ANHIVE";

    // special character to prefix the otp. Make sure this character appears only once in the sms
    public static final String OTP_DELIMITER = ":";
}

5. Under app package, create a class named MyApplication.java. This class initiates the volley core objects. This class extends from Application class which should be added in your AndroidManifest.xml <application> tag.

package info.androidhive.smsverification.app;

import android.app.Application;
import android.text.TextUtils;

import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.toolbox.Volley;

/**
 * Created by Ravi on 13/05/15.
 */

public class MyApplication extends Application {

    public static final String TAG = MyApplication.class
            .getSimpleName();

    private RequestQueue mRequestQueue;

    private static MyApplication mInstance;

    @Override
    public void onCreate() {
        super.onCreate();
        mInstance = this;
    }

    public static synchronized MyApplication getInstance() {
        return mInstance;
    }

    public RequestQueue getRequestQueue() {
        if (mRequestQueue == null) {
            mRequestQueue = Volley.newRequestQueue(getApplicationContext());
        }

        return mRequestQueue;
    }

    public <T> void addToRequestQueue(Request<T> req, String tag) {
        req.setTag(TextUtils.isEmpty(tag) ? TAG : tag);
        getRequestQueue().add(req);
    }

    public <T> void addToRequestQueue(Request<T> req) {
        req.setTag(TAG);
        getRequestQueue().add(req);
    }

    public void cancelPendingRequests(Object tag) {
        if (mRequestQueue != null) {
            mRequestQueue.cancelAll(tag);
        }
    }
}

6. Open your AndroidManifest.xml and add the MyApplication to <application> tag.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="info.androidhive.smsverification">

    <application
        android:name=".app.MyApplication" ..>
        .
        .

    </application>

</manifest>

7. Under helper package, create a class named MyViewPager.java. This is a custom ViewPager class where we disable the swipe functionality of it.

package info.androidhive.smsverification.helper;

import android.content.Context;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;

/**
 * Created by Ravi on 08/07/15.
 */
public class MyViewPager extends ViewPager {

    public MyViewPager(Context context) {
        super(context);
    }

    public MyViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        // Never allow swiping to switch between pages
        return false;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        // Never allow swiping to switch between pages
        return false;
    }
}

8. Create a class named PrefManager.java under helper package. This class contains methods to store user information in Shared Preferences.

package info.androidhive.smsverification.helper;

import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;

import java.util.HashMap;

/**
 * Created by Ravi on 08/07/15.
 */
public class PrefManager {
    // Shared Preferences
    SharedPreferences pref;

    // Editor for Shared preferences
    Editor editor;

    // Context
    Context _context;

    // Shared pref mode
    int PRIVATE_MODE = 0;

    // Shared preferences file name
    private static final String PREF_NAME = "AndroidHive";

    // All Shared Preferences Keys
    private static final String KEY_IS_WAITING_FOR_SMS = "IsWaitingForSms";
    private static final String KEY_MOBILE_NUMBER = "mobile_number";
    private static final String KEY_IS_LOGGED_IN = "isLoggedIn";
    private static final String KEY_NAME = "name";
    private static final String KEY_EMAIL = "email";
    private static final String KEY_MOBILE = "mobile";

    public PrefManager(Context context) {
        this._context = context;
        pref = _context.getSharedPreferences(PREF_NAME, PRIVATE_MODE);
        editor = pref.edit();
    }

    public void setIsWaitingForSms(boolean isWaiting) {
        editor.putBoolean(KEY_IS_WAITING_FOR_SMS, isWaiting);
        editor.commit();
    }

    public boolean isWaitingForSms() {
        return pref.getBoolean(KEY_IS_WAITING_FOR_SMS, false);
    }

    public void setMobileNumber(String mobileNumber) {
        editor.putString(KEY_MOBILE_NUMBER, mobileNumber);
        editor.commit();
    }

    public String getMobileNumber() {
        return pref.getString(KEY_MOBILE_NUMBER, null);
    }

    public void createLogin(String name, String email, String mobile) {
        editor.putString(KEY_NAME, name);
        editor.putString(KEY_EMAIL, email);
        editor.putString(KEY_MOBILE, mobile);
        editor.putBoolean(KEY_IS_LOGGED_IN, true);
        editor.commit();
    }

    public boolean isLoggedIn() {
        return pref.getBoolean(KEY_IS_LOGGED_IN, false);
    }

    public void clearSession() {
        editor.clear();
        editor.commit();
    }

    public HashMap<String, String> getUserDetails() {
        HashMap<String, String> profile = new HashMap<>();
        profile.put("name", pref.getString(KEY_NAME, null));
        profile.put("email", pref.getString(KEY_EMAIL, null));
        profile.put("mobile", pref.getString(KEY_MOBILE, null));
        return profile;
    }
}

6.1 Creating SMS Receiver

Now we’ll see how to add a receiver which will be triggered whenever the device receives an SMS. Also we’ll add an Intent Service to make the http calls when the app is not running.

9. Under service package, create a class named HttpService.java and extend this class from IntentService. This service is useful to make the HTTP calls when the app is in background or killed. We’ll use this Intent Service to send the OTP to our server if the app is killed before receiving the SMS.

package info.androidhive.smsverification.service;

import android.app.IntentService;
import android.content.Intent;
import android.util.Log;
import android.widget.Toast;

import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;

import org.json.JSONException;
import org.json.JSONObject;

import java.util.HashMap;
import java.util.Map;

import info.androidhive.smsverification.activity.MainActivity;
import info.androidhive.smsverification.app.Config;
import info.androidhive.smsverification.app.MyApplication;
import info.androidhive.smsverification.helper.PrefManager;

/**
 * Created by Ravi on 04/04/15.
 */
public class HttpService extends IntentService {

    private static String TAG = HttpService.class.getSimpleName();

    public HttpService() {
        super(HttpService.class.getSimpleName());
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        if (intent != null) {
            String otp = intent.getStringExtra("otp");
            verifyOtp(otp);
        }
    }

    /**
     * Posting the OTP to server and activating the user
     *
     * @param otp otp received in the SMS
     */
    private void verifyOtp(final String otp) {
        StringRequest strReq = new StringRequest(Request.Method.POST,
                Config.URL_VERIFY_OTP, new Response.Listener<String>() {

            @Override
            public void onResponse(String response) {
                Log.d(TAG, response.toString());

                try {

                    JSONObject responseObj = new JSONObject(response);

                    // Parsing json object response
                    // response will be a json object
                    boolean error = responseObj.getBoolean("error");
                    String message = responseObj.getString("message");

                    if (!error) {
                        // parsing the user profile information
                        JSONObject profileObj = responseObj.getJSONObject("profile");

                        String name = profileObj.getString("name");
                        String email = profileObj.getString("email");
                        String mobile = profileObj.getString("mobile");

                        PrefManager pref = new PrefManager(getApplicationContext());
                        pref.createLogin(name, email, mobile);

                        Intent intent = new Intent(HttpService.this, MainActivity.class);
                        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                        startActivity(intent);

                        Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show();

                    } else {
                        Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show();
                    }

                } catch (JSONException e) {
                    Toast.makeText(getApplicationContext(),
                            "Error: " + e.getMessage(),
                            Toast.LENGTH_LONG).show();
                }

            }
        }, new Response.ErrorListener() {

            @Override
            public void onErrorResponse(VolleyError error) {
                Log.e(TAG, "Error: " + error.getMessage());
                Toast.makeText(getApplicationContext(),
                        error.getMessage(), Toast.LENGTH_SHORT).show();
            }
        }) {

            @Override
            protected Map<String, String> getParams() {
                Map<String, String> params = new HashMap<String, String>();
                params.put("otp", otp);

                Log.e(TAG, "Posting params: " + params.toString());
                return params;
            }

        };

        // Adding request to request queue
        MyApplication.getInstance().addToRequestQueue(strReq);
    }

}

9. Now under receiver package, create a class named SmsReceiver.java and extend the class from BroadcastReceiver. This is a broadcast receiver class which will be triggered whenever user device receives the SMS.

package info.androidhive.smsverification.receiver;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.SmsMessage;
import android.util.Log;

import info.androidhive.smsverification.app.Config;
import info.androidhive.smsverification.service.HttpService;

/**
 * Created by Ravi on 09/07/15.
 */
public class SmsReceiver extends BroadcastReceiver {
    private static final String TAG = SmsReceiver.class.getSimpleName();

    @Override
    public void onReceive(Context context, Intent intent) {

        final Bundle bundle = intent.getExtras();
        try {
            if (bundle != null) {
                Object[] pdusObj = (Object[]) bundle.get("pdus");
                for (Object aPdusObj : pdusObj) {
                    SmsMessage currentMessage = SmsMessage.createFromPdu((byte[]) aPdusObj);
                    String senderAddress = currentMessage.getDisplayOriginatingAddress();
                    String message = currentMessage.getDisplayMessageBody();

                    Log.e(TAG, "Received SMS: " + message + ", Sender: " + senderAddress);

                    // if the SMS is not from our gateway, ignore the message
                    if (!senderAddress.toLowerCase().contains(Config.SMS_ORIGIN.toLowerCase())) {
                        return;
                    }

                    // verification code from sms
                    String verificationCode = getVerificationCode(message);

                    Log.e(TAG, "OTP received: " + verificationCode);

                    Intent hhtpIntent = new Intent(context, HttpService.class);
                    hhtpIntent.putExtra("otp", verificationCode);
                    context.startService(hhtpIntent);
                }
            }
        } catch (Exception e) {
            Log.e(TAG, "Exception: " + e.getMessage());
        }
    }

    /**
     * Getting the OTP from sms message body
     * ':' is the separator of OTP from the message
     *
     * @param message
     * @return
     */
    private String getVerificationCode(String message) {
        String code = null;
        int index = message.indexOf(Config.OTP_DELIMITER);

        if (index != -1) {
            int start = index + 2;
            int length = 6;
            code = message.substring(start, start + length);
            return code;
        }

        return code;
    }
}

10. To make the service and receiver working, open the AndroidManifest.xml and do the below changes.

> Add INTERNET, RECEIVE_SMS and READ_SMS permissions.

> Add MyApplication to <application> tag.

> Make SmsActivity as launcher activity. (We’ll create this activity shortly)

> Add SmsReceiver class using <receiver> tag.

> Add HttpService using <service> tag.

This is how your manifest file should look like.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="info.androidhive.smsverification">

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.RECEIVE_SMS" />
    <uses-permission android:name="android.permission.READ_SMS" />

    <application
        android:name=".app.MyApplication"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/MyMaterialTheme">

        <activity
            android:name=".activity.SmsActivity"
            android:label="@string/title_activity_sms">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <activity
            android:name=".activity.MainActivity"
            android:label="@string/app_name"
            android:windowSoftInputMode="adjustResize">

        </activity>

        <!-- SMS Receiver -->
        <receiver android:name=".receiver.SmsReceiver">
            <intent-filter android:priority="99999">
                <action android:name="android.provider.Telephony.SMS_RECEIVED" />
            </intent-filter>
        </receiver>


        <!-- Intent service -->
        <service
            android:name=".service.HttpService"
            android:exported="false" />

    </application>

</manifest>

6.2 Creating Mobile Login Screen

Now we have all the core logic ready. Let’s add the first activity to enter the mobile number and OTP.

12. Under res ⇒ layout, create an xml layout named activity_sms.xml and add below code. This layout contains a ViewPager with two pages. In one page we ask the user to enter his mobile number. In the second page we prompt the user to enter the OTP if the automatic sms verification fails.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/viewContainer"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="info.androidhive.smsverification.activity.SmsActivity">

    <info.androidhive.smsverification.helper.MyViewPager
        android:id="@+id/viewPagerVertical"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent">

        <LinearLayout
            android:id="@+id/layout_sms"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:background="@color/colorPrimary"
            android:gravity="center_horizontal"
            android:orientation="vertical">

            <ImageView
                android:layout_width="60dp"
                android:layout_height="60dp"
                android:layout_gravity="center_horizontal"
                android:layout_marginBottom="25dp"
                android:layout_marginTop="100dp"
                android:src="@mipmap/ic_launcher" />

            <TextView
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:layout_marginBottom="25dp"
                android:gravity="center_horizontal"
                android:inputType="textCapWords"
                android:paddingLeft="40dp"
                android:paddingRight="40dp"
                android:text="@string/msg_enter_mobile"
                android:textColor="@android:color/white"
                android:textSize="14dp" />

            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="vertical">

                <EditText
                    android:id="@+id/inputName"
                    android:layout_width="fill_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginBottom="15dp"
                    android:background="@android:color/white"
                    android:fontFamily="sans-serif-light"
                    android:hint="@string/lbl_name"
                    android:padding="5dp"
                    android:singleLine="true"
                    android:textColor="@color/colorPrimary"
                    android:textSize="18dp" />

                <EditText
                    android:id="@+id/inputEmail"
                    android:layout_width="fill_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginBottom="15dp"
                    android:background="@android:color/white"
                    android:fontFamily="sans-serif-light"
                    android:hint="@string/lbl_email"
                    android:inputType="textEmailAddress"
                    android:padding="5dp"
                    android:textColor="@color/colorPrimary"
                    android:textSize="18dp" />

                <EditText
                    android:id="@+id/inputMobile"
                    android:layout_width="240dp"
                    android:layout_height="wrap_content"
                    android:background="@android:color/white"
                    android:fontFamily="sans-serif-light"
                    android:hint="@string/lbl_mobile"
                    android:inputType="phone"
                    android:maxLength="10"
                    android:padding="5dp"
                    android:textColor="@color/colorPrimary"
                    android:textCursorDrawable="@null"
                    android:textSize="18dp" />

                <Button
                    android:id="@+id/btn_request_sms"
                    android:layout_width="fill_parent"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center_horizontal"
                    android:layout_marginTop="25dp"
                    android:background="@color/colorPrimaryDark"
                    android:text="@string/lbl_next"
                    android:textColor="@android:color/white"
                    android:textSize="14dp" />
            </LinearLayout>


        </LinearLayout>

        <LinearLayout
            android:id="@+id/layout_otp"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:background="@color/colorPrimary"
            android:gravity="center_horizontal"
            android:orientation="vertical">

            <ImageView
                android:layout_width="60dp"
                android:layout_height="60dp"
                android:layout_gravity="center_horizontal"
                android:layout_marginBottom="25dp"
                android:layout_marginTop="100dp"
                android:src="@mipmap/ic_launcher" />

            <TextView
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:layout_marginBottom="15dp"
                android:gravity="center_horizontal"
                android:paddingLeft="40dp"
                android:paddingRight="40dp"
                android:text="@string/msg_sit_back"
                android:textColor="@android:color/white"
                android:textSize="16dp" />

            <TextView
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:layout_marginBottom="25dp"
                android:gravity="center_horizontal"
                android:paddingLeft="40dp"
                android:paddingRight="40dp"
                android:text="@string/msg_manual_otp"
                android:textColor="@android:color/white"
                android:textSize="12dp" />

            <EditText
                android:id="@+id/inputOtp"
                android:layout_width="120dp"
                android:layout_height="wrap_content"
                android:background="@android:color/white"
                android:fontFamily="sans-serif-light"
                android:gravity="center_horizontal"
                android:hint="@string/lbl_enter_otp"
                android:inputType="number"
                android:maxLength="6"
                android:padding="10dp"
                android:textCursorDrawable="@null"
                android:textSize="18dp" />

            <Button
                android:id="@+id/btn_verify_otp"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_horizontal"
                android:layout_marginTop="25dp"
                android:background="@color/colorPrimaryDark"
                android:paddingLeft="20dp"
                android:paddingRight="20dp"
                android:text="@string/lbl_submit"
                android:textColor="@android:color/white"
                android:textSize="14dp" />

        </LinearLayout>

    </info.androidhive.smsverification.helper.MyViewPager>


    <ProgressBar
        android:id="@+id/progressBar"
        android:layout_width="30dp"
        android:layout_height="30dp"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:layout_gravity="center"
        android:layout_marginBottom="60dp"
        android:indeterminateTint="@color/colorAccent"
        android:indeterminateTintMode="src_atop"
        android:visibility="gone" />

    <LinearLayout
        android:id="@+id/layout_edit_mobile"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_marginBottom="50dp"
        android:gravity="center"
        android:orientation="horizontal">

        <TextView
            android:id="@+id/txt_edit_mobile"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="@android:color/white"
            android:textSize="16dp" />

        <ImageButton
            android:id="@+id/btn_edit_mobile"
            android:layout_width="40dp"
            android:layout_height="40dp"
            android:layout_marginLeft="10dp"
            android:background="@null"
            android:src="@drawable/ic_edit_mobile" />
    </LinearLayout>

</RelativeLayout>

13. Create an activity class named SmsActivity.java under activity package. In the below code

> requestForSMS() method make a call to server by passing name, email and mobile requesting for sms.

> verifyOtp() methods passes the otp received in the SMS to server to verify it.

package info.androidhive.smsverification.activity;

import android.content.Intent;
import android.os.Bundle;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;

import org.json.JSONException;
import org.json.JSONObject;

import java.util.HashMap;
import java.util.Map;

import info.androidhive.smsverification.R;
import info.androidhive.smsverification.app.Config;
import info.androidhive.smsverification.app.MyApplication;
import info.androidhive.smsverification.helper.PrefManager;
import info.androidhive.smsverification.service.HttpService;

public class SmsActivity extends AppCompatActivity implements View.OnClickListener {

    private static String TAG = SmsActivity.class.getSimpleName();

    private ViewPager viewPager;
    private ViewPagerAdapter adapter;
    private Button btnRequestSms, btnVerifyOtp;
    private EditText inputName, inputEmail, inputMobile, inputOtp;
    private ProgressBar progressBar;
    private PrefManager pref;
    private ImageButton btnEditMobile;
    private TextView txtEditMobile;
    private LinearLayout layoutEditMobile;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_sms);

        viewPager = (ViewPager) findViewById(R.id.viewPagerVertical);
        inputName = (EditText) findViewById(R.id.inputName);
        inputEmail = (EditText) findViewById(R.id.inputEmail);
        inputMobile = (EditText) findViewById(R.id.inputMobile);
        inputOtp = (EditText) findViewById(R.id.inputOtp);
        btnRequestSms = (Button) findViewById(R.id.btn_request_sms);
        btnVerifyOtp = (Button) findViewById(R.id.btn_verify_otp);
        progressBar = (ProgressBar) findViewById(R.id.progressBar);
        btnEditMobile = (ImageButton) findViewById(R.id.btn_edit_mobile);
        txtEditMobile = (TextView) findViewById(R.id.txt_edit_mobile);
        layoutEditMobile = (LinearLayout) findViewById(R.id.layout_edit_mobile);

        // view click listeners
        btnEditMobile.setOnClickListener(this);
        btnRequestSms.setOnClickListener(this);
        btnVerifyOtp.setOnClickListener(this);

        // hiding the edit mobile number
        layoutEditMobile.setVisibility(View.GONE);

        pref = new PrefManager(this);

        // Checking for user session
        // if user is already logged in, take him to main activity
        if (pref.isLoggedIn()) {
            Intent intent = new Intent(SmsActivity.this, MainActivity.class);
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
            startActivity(intent);

            finish();
        }

        adapter = new ViewPagerAdapter();
        viewPager.setAdapter(adapter);
        viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            }

            @Override
            public void onPageSelected(int position) {
            }

            @Override
            public void onPageScrollStateChanged(int state) {

            }
        });


        /**
         * Checking if the device is waiting for sms
         * showing the user OTP screen
         */
        if (pref.isWaitingForSms()) {
            viewPager.setCurrentItem(1);
            layoutEditMobile.setVisibility(View.VISIBLE);
        }
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.btn_request_sms:
                validateForm();
                break;

            case R.id.btn_verify_otp:
                verifyOtp();
                break;

            case R.id.btn_edit_mobile:
                viewPager.setCurrentItem(0);
                layoutEditMobile.setVisibility(View.GONE);
                pref.setIsWaitingForSms(false);
                break;
        }
    }

    /**
     * Validating user details form
     */
    private void validateForm() {
        String name = inputName.getText().toString().trim();
        String email = inputEmail.getText().toString().trim();
        String mobile = inputMobile.getText().toString().trim();

        // validating empty name and email
        if (name.length() == 0 || email.length() == 0) {
            Toast.makeText(getApplicationContext(), "Please enter your details", Toast.LENGTH_SHORT).show();
            return;
        }

        // validating mobile number
        // it should be of 10 digits length
        if (isValidPhoneNumber(mobile)) {

            // request for sms
            progressBar.setVisibility(View.VISIBLE);

            // saving the mobile number in shared preferences
            pref.setMobileNumber(mobile);

            // requesting for sms
            requestForSMS(name, email, mobile);

        } else {
            Toast.makeText(getApplicationContext(), "Please enter valid mobile number", Toast.LENGTH_SHORT).show();
        }
    }

    /**
     * Method initiates the SMS request on the server
     *
     * @param name   user name
     * @param email  user email address
     * @param mobile user valid mobile number
     */
    private void requestForSMS(final String name, final String email, final String mobile) {
        StringRequest strReq = new StringRequest(Request.Method.POST,
                Config.URL_REQUEST_SMS, new Response.Listener<String>() {

            @Override
            public void onResponse(String response) {
                Log.d(TAG, response.toString());

                try {
                    JSONObject responseObj = new JSONObject(response);

                    // Parsing json object response
                    // response will be a json object
                    boolean error = responseObj.getBoolean("error");
                    String message = responseObj.getString("message");

                    // checking for error, if not error SMS is initiated
                    // device should receive it shortly
                    if (!error) {
                        // boolean flag saying device is waiting for sms
                        pref.setIsWaitingForSms(true);

                        // moving the screen to next pager item i.e otp screen
                        viewPager.setCurrentItem(1);
                        txtEditMobile.setText(pref.getMobileNumber());
                        layoutEditMobile.setVisibility(View.VISIBLE);

                        Toast.makeText(getApplicationContext(), message, Toast.LENGTH_SHORT).show();

                    } else {
                        Toast.makeText(getApplicationContext(),
                                "Error: " + message,
                                Toast.LENGTH_LONG).show();
                    }

                    // hiding the progress bar
                    progressBar.setVisibility(View.GONE);

                } catch (JSONException e) {
                    Toast.makeText(getApplicationContext(),
                            "Error: " + e.getMessage(),
                            Toast.LENGTH_LONG).show();

                    progressBar.setVisibility(View.GONE);
                }

            }
        }, new Response.ErrorListener() {

            @Override
            public void onErrorResponse(VolleyError error) {
                Log.e(TAG, "Error: " + error.getMessage());
                Toast.makeText(getApplicationContext(),
                        error.getMessage(), Toast.LENGTH_SHORT).show();
                progressBar.setVisibility(View.GONE);
            }
        }) {

            /**
             * Passing user parameters to our server
             * @return
             */
            @Override
            protected Map<String, String> getParams() {
                Map<String, String> params = new HashMap<String, String>();
                params.put("name", name);
                params.put("email", email);
                params.put("mobile", mobile);

                Log.e(TAG, "Posting params: " + params.toString());

                return params;
            }

        };

        // Adding request to request queue
        MyApplication.getInstance().addToRequestQueue(strReq);
    }

    /**
     * sending the OTP to server and activating the user
     */
    private void verifyOtp() {
        String otp = inputOtp.getText().toString().trim();

        if (!otp.isEmpty()) {
            Intent grapprIntent = new Intent(getApplicationContext(), HttpService.class);
            grapprIntent.putExtra("otp", otp);
            startService(grapprIntent);
        } else {
            Toast.makeText(getApplicationContext(), "Please enter the OTP", Toast.LENGTH_SHORT).show();
        }
    }

    /**
     * Regex to validate the mobile number
     * mobile number should be of 10 digits length
     *
     * @param mobile
     * @return
     */
    private static boolean isValidPhoneNumber(String mobile) {
        String regEx = "^[0-9]{10}$";
        return mobile.matches(regEx);
    }


    class ViewPagerAdapter extends PagerAdapter {

        @Override
        public int getCount() {
            return 2;
        }

        @Override
        public boolean isViewFromObject(View view, Object object) {
            return view == ((View) object);
        }

        public Object instantiateItem(View collection, int position) {

            int resId = 0;
            switch (position) {
                case 0:
                    resId = R.id.layout_sms;
                    break;
                case 1:
                    resId = R.id.layout_otp;
                    break;
            }
            return findViewById(resId);
        }
    }

}

Now run the app and test it once. Make sure that you have correct ip address of your localhost in Config.java

android-sms-verification-like-whatsapp-viber
android-sms-verification-like-whatsapp-viber-otp

6.2 Displaying logged in User Profile

Displaying the logged in user information is pretty straight forward. Previously the user information is store in Shared Preferences in HttpService.class. In this activity we have to read the information from shared preferences and display it on the screen.

14. Create an xml layout named toolbar.xml under res ⇒ layout.

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:local="http://schemas.android.com/apk/res-auto"
    android:id="@+id/toolbar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:minHeight="?attr/actionBarSize"
    android:background="?attr/colorPrimary"
    local:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
    local:popupTheme="@style/ThemeOverlay.AppCompat.Light" />

15. Open the layout file your main activity (activity_main.xml) and do the below changes. This layout contains few TextViews to display the logged in user information.

<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"
    tools:context=".MainActivity">

    <LinearLayout
        android:id="@+id/layout_toolbar"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:orientation="vertical">

        <include
            android:id="@+id/toolbar"
            layout="@layout/toolbar" />
    </LinearLayout>

    <LinearLayout
        android:id="@+id/layout_mobile"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:orientation="vertical">

        <TextView
            android:id="@+id/name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="10dp"
            android:textSize="18dp" />

        <TextView
            android:id="@+id/email"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="10dp"
            android:textSize="18dp" />

        <TextView
            android:id="@+id/mobile"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="10dp"
            android:textSize="18dp" />

    </LinearLayout>
</RelativeLayout>

17. Open menu_main.xml located under res ⇒ menu and add an action item to provide the logout option.

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context=".MainActivity">
    <item
        android:id="@+id/action_logout"
        android:orderInCategory="100"
        android:title="@string/action_logout"
        app:showAsAction="always" />
</menu>

16. Open MainActivity.java and do the below changes. In this activity we just read the user information stored in shared preferences and display it on the screen.

package info.androidhive.smsverification.activity;

import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TextView;

import java.util.HashMap;

import info.androidhive.smsverification.R;
import info.androidhive.smsverification.helper.PrefManager;


public class MainActivity extends AppCompatActivity {

    private Toolbar toolbar;
    private PrefManager pref;
    private TextView name, email, mobile;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        toolbar = (Toolbar) findViewById(R.id.toolbar);
        name = (TextView) findViewById(R.id.name);
        email = (TextView) findViewById(R.id.email);
        mobile = (TextView) findViewById(R.id.mobile);

        // enabling toolbar
        setSupportActionBar(toolbar);
        getSupportActionBar().setDisplayShowHomeEnabled(true);

        pref = new PrefManager(getApplicationContext());


        // Checking if user session
        // if not logged in, take user to sms screen
        if (!pref.isLoggedIn()) {
            logout();
        }

        // Displaying user information from shared preferences
        HashMap<String, String> profile = pref.getUserDetails();
        name.setText("Name: " + profile.get("name"));
        email.setText("Email: " + profile.get("email"));
        mobile.setText("Mobile: " + profile.get("mobile"));
    }

    /**
     * Logging out user
     * will clear all user shared preferences and navigate to
     * sms activation screen
     */
    private void logout() {
        pref.clearSession();

        Intent intent = new Intent(MainActivity.this, SmsActivity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);

        startActivity(intent);

        finish();
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_logout) {
            logout();
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}

android-sms-verification-like-whatsapp-viber-1

7. Testing the App

To test the app, carefully follow the below steps.

> Make sure that your device and the PC running the php project are under the same wifi network.

> Keep correct username, password and database name in Config.php

> Give the correct MSG91_AUTH_KEY Key in Config.php

> Make sure that MSG91_SENDER_ID in Config.java and SMS_ORIGIN in Config.java are equal.

> Keep the correct ip address of your localhost in Config.java. On windows run ipconfig in command prompt to get the ip address.

I know running this app is little tricky for a beginner. But the following the above steps correctly will help you a lot. If you are still facing the problem in running this app, please do comment below.

Subscribe
Notify of
guest
240 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
tigani jaber
tigani jaber
6 years ago

Ravi always guru

Ankesh Roy
Ankesh Roy
5 years ago
Reply to  tigani jaber

can any one have idea about such example in java in place of php(part one of this example)??? because i don’t know php please help if any one can….Thanks in advance….???

EBLiS
EBLiS
6 years ago

Hi Ravi
Nice job,But there’s a problem
In an IntentService the service dies as soon as it finishes the last line in onHandleIntent(), so the async volley onResponse() call won’t behave nicely, the solution is to use a service instead or make the call synchronous

Ravi Tamada
6 years ago
Reply to  EBLiS

Oh really! I am using the same code in a real app and haven’t faced any problem until now. Anyways I’ll look into your suggestion.

EBLiS
EBLiS
6 years ago
Reply to  Ravi Tamada

I thinks its because of your connection speed,which returns response as fast as service is still alive, otherwise one might get service leaked

Ravi Tamada
6 years ago
Reply to  EBLiS

OK.

Riyas V
Riyas V
6 years ago
Reply to  Ravi Tamada

@disqus_VwSWmULpCr:disqus : There is no such problem as EBLiS says even if the IntentService dies as soon as it finishes. You can test this by putting Log text at the end of both IntentService.onRecieve and Volley’s onResponse methods. then you can see that even after IntentSerivice dies Volley recieve and respond to the response. I think it is because the Context object still lives in memory.

Rajesh J Nair
Rajesh J Nair
6 years ago

Nice Article Ravi… Helpful….
Can we detect the phone no Automatically?

Tarigonda Sekhar
Tarigonda Sekhar
6 years ago

Hi Ravi…Is there any example code for storing data into sql instead of using sqlite ?

Ravi Tamada
6 years ago

You need to understand what is SQL and SQLite.

SQL – Structured Query Language. Its a common language to perform queries on to any database like MySQL, SQLServer, Oracle, SQLite etc.,

SQLite – Is a database just like MySQL, Oracle etc.,

YoungUser
YoungUser
6 years ago

Hi Ravi,

First, thank you for your work, it is really helpfull to me !
But I have some questions to create a kind of ecommerce application.

When the user installs the application and launches it for the first time, the login page appears , with a link to register. Let’s suppose the guy creates his account, login with it and turn of his phone. Two days later he launch the app again , how to avoid the login screen? Do I have to make a blank activity (which would be the launcher activity) and check if an account is stored in memory or something like that ? and do you have some tutorial for that? 😀

Thank you <3 !

Ravi Tamada
6 years ago
Reply to  YoungUser

You are correct. Make the login screen as launcher activity. Check the user stored data each time app launches. Stay in login screen if user is not logged in or launch the main activity if he is already logged in.

Here the trick is check the session before calling setContentView() to avoid the login view to be shown to user.

Keep the user session in Shared Preferences, SQLite or Accounts.

Trey Rosius
Trey Rosius
6 years ago
Reply to  Ravi Tamada

Hmmm @Ravi Tamada, does it make sense if i create a splash screen to check if user is logged in or not.Like if user is logged in, take him to the home page, else take him to the login page?

Ravi Tamada
6 years ago
Reply to  Trey Rosius

You really don’t need another splash screen. You can implement same logic in login screen too (before setContentView()). But it is up to you.

Darude
Darude
6 years ago

Hello Ravi,

I have a question concerning a previous tutorial, unfortunetly, I cannot see the ” discuss” on it so I ask it here ^^’ (this one : http://www.androidhive.info/2012/01/android-login-and-registration-with-php-mysql-and-sqlite/)

I followed the different step in your tutorial but at the end , I get an error when I try to login or register an account :'(

Here is a screenshot of what i have… do you have any idea to solve this? thank you ! ^^

http://hpics.li/a66747d

Ravi Tamada
6 years ago
Reply to  Darude

Have you added AppController to your AndroidManifest.xml’s application tag?

Darude
Darude
6 years ago
Reply to  Ravi Tamada

Great, now it works almost ^^

When I create an account through the application, it goes well into the database, but when I want to login on it I have a problem, the mainscreen is not displayed

and I have those warnings : http://hpics.li/e52f8d1 :'(

Ravi Tamada
6 years ago
Reply to  Darude

Yeah, It seems PHP version difference. It’s actually my problem. I still left older mysql functions in DB_Connect.php. Try to make them mysqli.

yajas sonu
yajas sonu
6 years ago

heloo, i ve doubt please help me, in my signup page if a user sign up and register in the page how the datas should be stored in my server or database? how to connect my app to database for storing and retrieving the datas? kindly please help me..

Rendy
Rendy
6 years ago

BroadcastReceiver incoming sms not working
what should i do?
thanks

Rakhi Dhavale
6 years ago

I wanted to learn this since long time and finally Android hive posted this, thanks a ton !!!

Ravi Tamada
6 years ago
Reply to  Rakhi Dhavale

You are welcome 😀

Amin M
Amin M
6 years ago

Hi ravi thanks for this awesome tuts

i have problem with these one (http://www.androidhive.info/2014/07/android-custom-listview-with-image-and-text-using-volley/)

i see that u don’t answer the question’s there so i will ask u here if u don’t mind
i created the app successfully but when i run it, it show’s the Dialog and when the Dialog’s go away
i just see a blank page

i made these changes

1-i didn’t want the genre and rating sow i removed theme from whole code
2-and this is my Json https://api.myjson.com/bins/1hv2s

i really appreciate that if you answer’d me ,i searched for hour’s and no clue i didn’t find the answer on stackOverFlow or even the whole google and i don’t know what’s the problem
and my logCat not even helping me , so can you help me please? i really want it, thank’s
if u can’t answer here please mail me at [email protected]

Ravi Tamada
6 years ago
Reply to  Amin M

Can you post your code in Pastebin or somewhere?

Amin M
Amin M
6 years ago
Reply to  Ravi Tamada

ok ravi this is the code in Pastebin(http://pastebin.ca/3093524)
i’m sorry if it was messy a little bit and thank you for helping me i really appreciate that

Ravi Tamada
6 years ago
Reply to  Amin M

Got the bug. You have a spelling mistake in MainActivity.java while parsing the json. Just correct it, everything worked well 🙂

The title is spelled wrong (tittle).

movie.setTitle(obj.getString(“tittle”));

Amin M
Amin M
6 years ago
Reply to  Ravi Tamada

WTF?? and i was thinking about it all the time and that was just this?,a single (t)? that’s a bug that u can’t find it easily thanks a lot ravi u made my day

Ravi Tamada
6 years ago
Reply to  Amin M

You are welcome 🙂

Darsh m
Darsh m
6 years ago

hi ravi, thanks for your tutorials its very helpful, can you help me with pdf creation with any free library ?

bo3bdo
6 years ago

it does help me alot but User After logout he can not login again .. need login class ?

if he register again he get Mobile number already existed

Rob
Rob
6 years ago

Wonderful job Ravi ! Thanks a lot again 🙂

Kemei
Kemei
6 years ago

Ravi,thanks alot brother,awesome job!!

Mohammad
Mohammad
5 years ago

I wanted to learn this since long time and finally Android hive posted this, thanks a ton !!!

Praneeth Nandi
Praneeth Nandi
5 years ago

Hello Ravi garu Iam using Eclipse i added Volley in java built path iam getting errors like FETAL EXCEPTION Myapplication class not found can u please give me the sugession…. i required it urgent it will help me more……

Kadir Khaniya
Kadir Khaniya
5 years ago

Thenkyou Werymach

Okechukwu Eze
Okechukwu Eze
5 years ago

i keep getting this error

java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{okechukwu.com.smsverificationapp/okechukwu.com.smsverificationapp.MyApplication}: java.lang.ClassCastException: okechukwu.com.smsverificationapp.MyApplication cannot be cast to android.app.Activity

and even before execution, my manifest file keeps flagging the same error on

android:name=”.app.MyApplication”

The amazing thing is the copy i downloaded online works fine.
I have been debugging this same issue for about 2 days and i cant seem to figure out my own app
is flagging that message that “MyApplication is not assignable to android.app.Activity”

can you guyz tell me what i am not doing right cos my eyez are already itching me!

Edward Rana
Edward Rana
5 years ago

Dear Sir .. How can I check If User send a Fake OTP by Fake sms Sender App.
For more security what can I add in your code??

Ravi Tamada
5 years ago
Reply to  Edward Rana

Nothing will happen if he uses FAKE OTP as the OTP has to matched in our MySQL database.

sam xfido
sam xfido
5 years ago

great tutorial bro!!!!! im beginner in android app devlopment !! wen i try to connect it showing java null exception and when i try to check the api in postman its showing “Access denied for user ‘root’@’localhost’ (using password: YES) in C:wampwwwandroid_smsincludeDbConnect.php on line “”. plzz do help !! thanks in advance

Akanksha Verma
Akanksha Verma
5 years ago
Reply to  sam xfido

in Config.php, change the value of password to ”
see this:
define(‘DB_USERNAME’, ‘root’);
define(‘DB_PASSWORD’, ”);

Nikhil Gaur
Nikhil Gaur
5 years ago

Hi, I found two issues with your above application.

1. If sending SMS takes longer then request gets terminated automatically. So please tell me where I can increase the timeout for all requests.

2. When I tried to use your code in both the articles it fires request_sms request two times. Do you know how can I resolve this?

amit basliyal
amit basliyal
5 years ago

i am getting an error

MyApplication.getInstance().addToRequestQueue(strReq);

java.lang.NullPointerException: Attempt to invoke virtual method ‘void com.example.com.inside_sms_sending.app.MyApplication.addToRequestQueue(com.android.volley.Request)’ on a null object reference

Adhik Joshi
Adhik Joshi
5 years ago

I am getting a error of “Failed to connect to MySQL: Access denied for user ‘kjpzefcvgw’@’localhost’ (using password: YES)”

and i have changed all links including host, db name, user name, but still it gives error like this..

m using online php hosting server, with PHP 5.5, and MySQL 5.5.

Don
Don
5 years ago
Reply to  Adhik Joshi

user password is wrong..and no longer access to it.

Sin
Sin
5 years ago

do I need the broadcast receiver? It is just to display the notification, isn’t it?

Bala Kumar
Bala Kumar
5 years ago

Hey hi after i am running this code i am getting the error like this

:[ Error:Execution failed for task ‘:app:transformClassesWithJarMergingForDebug’.
> com.android.build.api.transform.TransformException: java.util.zip.ZipException: duplicate entry: org/apache/http/message/BasicHeaderElementIterator.class ]..

How to clear this error ?

Himanshi Jain
Himanshi Jain
5 years ago

I have verified the server side code using postman successfully but on the client side when i run the code it ultimately shows a VOLLEY TIMEOUT ERROR.

The log inside the Response Listener does not show up.

The final String Request displays:

12-23 00:51:21.870 10282-10282/info.androidhive.smsverification I/Request﹕ [ ] http://192.168.1.101:80/request_sms.php 0x355f91a NORMAL null

The link :

http://192.168.1.101:80/request_sms.php

when clicked shows up the json string with
{“error”:true,”message”:”Sorry! mobile number is not valid or missing.”}

but the log : Posting params with the entered parameters is shown that too twice(maybe because of the retry policy)

I have not changed the code by any means.

I have tried to search the internet but got nothing. please help.

Thank You!

Nikhil Besra
Nikhil Besra
5 years ago
Reply to  Himanshi Jain

Did you get the solution?

Himanshi
Himanshi
5 years ago
Reply to  Nikhil Besra

yes i had got the solution!! I had to turn my windows firewall off to let my mobile device use my local server . i spent a complete day and a half to figure that out.

Ravi Tamada
5 years ago
Reply to  Himanshi

Congrats Himanshi 🙂

Harsh Dalwadi
Harsh Dalwadi
5 years ago

I have one issue .
I got this error :
java.net.ConnectException: failed to connect to /127.0.0.1 (port 80) after 2500ms: isConnected failed: ECONNREFUSED (Connection refused)

Please help :disqus .

mahmoud Abbas
mahmoud Abbas
5 years ago

it work…thanks ravi

Karjol GT
Karjol GT
5 years ago

Ravi,

thanks for the nice article.

but in the Application when i click next button i get this error
Error:value?>of type java.lang.String cannot be converted to JasonObject

Varun Vashista
Varun Vashista
5 years ago

hey ravi after using the code above in my app exactly everything is fine but in database two fields are adding and two sms are getting to the mobile which i used to register please help me about this thank you its a bit urgent

Ravi Tamada
5 years ago
Reply to  Varun Vashista

I already added logic that to handle multiple SMS in case there is a delay. I think this should work perfectly. Please test and let me know.

Varun Vashista
Varun Vashista
5 years ago
Reply to  Ravi Tamada

got it buddy thank you, another thing sms is not automatically detected by the app can you please help me out this 🙂 TIA

Ravi Tamada
5 years ago
Reply to  Varun Vashista

Yeah, it’s the problem with lot of manufacturers. You need to have a EditText to manually enter the OTP.

Varun Vashista
Varun Vashista
5 years ago
Reply to  Ravi Tamada

hey ravi thanks for your replies but im using msg91 itself even though its not detecting , is there any other manufacturers do i need to go for??

Ravi Tamada
5 years ago
Reply to  Varun Vashista

Hey varun, I am talking about manufacturers who build the mobile devices like HTC, Lenovo, LG etc., They normally build a flavour of their own OS on top of Android OS. This is why few things won’t work on their devices.

Varun Vashista
Varun Vashista
5 years ago
Reply to  Ravi Tamada

ohh!! thanks buddy 🙂 thank you so much 🙂

Raunak Bidasaria
Raunak Bidasaria
5 years ago

Hello, I am bit new to this and I have implemented most of the project. I have been using eclipse and most of the errors I am getting is in the themes of the xml files. I have added successful version of library as well. I would be glad if u could help me with the issue.

Nikhil Besra
Nikhil Besra
5 years ago

Everything is working fine on POSTMAN.but when i try to run app in Android studio,it is not able to post params. What could be the reason??

Ravi Tamada
5 years ago
Reply to  Nikhil Besra

Give me your volley request code.

Nikhil Besra
Nikhil Besra
5 years ago
Reply to  Ravi Tamada

(httpservice.java file) http://ideone.com/T1Uu9k
(myApplication.java) http://ideone.com/GuYyFE
(SmsActivity.java) http://ideone.com/uciEal

Nikhil Besra
Nikhil Besra
5 years ago
Reply to  Ravi Tamada
Nikhil Besra
Nikhil Besra
5 years ago
Reply to  Ravi Tamada
Nikhil Besra
Nikhil Besra
5 years ago
Reply to  Ravi Tamada

package info.androidhive.smsverification.service;

import android.app.IntentService;
import android.content.Intent;
import android.util.Log;
import android.widget.Toast;

import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;

import org.json.JSONException;
import org.json.JSONObject;

import java.util.HashMap;
import java.util.Map;

import info.androidhive.smsverification.activity.MainActivity;
import info.androidhive.smsverification.app.Config;
import info.androidhive.smsverification.app.MyApplication;
import info.androidhive.smsverification.helper.PrefManager;

/**
* Created by Ravi on 04/04/15.
*/
public class HttpService extends IntentService {

private static String TAG = HttpService.class.getSimpleName();

public HttpService() {
super(HttpService.class.getSimpleName());
}

@Override
protected void onHandleIntent(Intent intent) {
if (intent != null) {
String otp = intent.getStringExtra(“otp”);
verifyOtp(otp);
}
}

/**
* Posting the OTP to server and activating the user
*
* @param otp otp received in the SMS
*/
private void verifyOtp(final String otp) {
StringRequest strReq = new StringRequest(Request.Method.POST,
Config.URL_VERIFY_OTP, new Response.Listener() {

@Override
public void onResponse(String response) {
Log.d(TAG, response.toString());

try {

JSONObject responseObj = new JSONObject(response);

// Parsing json object response
// response will be a json object
boolean error = responseObj.getBoolean(“error”);
String message = responseObj.getString(“message”);

if (!error) {
// parsing the user profile information
JSONObject profileObj = responseObj.getJSONObject(“profile”);

String name = profileObj.getString(“name”);
String email = profileObj.getString(“email”);
String mobile = profileObj.getString(“mobile”);

PrefManager pref = new PrefManager(getApplicationContext());
pref.createLogin(name, email, mobile);

Intent intent = new Intent(HttpService.this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);

Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show();

} else {
Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show();
}

} catch (JSONException e) {
Toast.makeText(getApplicationContext(),
“Error: ” + e.getMessage(),
Toast.LENGTH_LONG).show();
}

}
}, new Response.ErrorListener() {

@Override
public void onErrorResponse(VolleyError error) {
Log.e(TAG, “Error: ” + error.getMessage());
Toast.makeText(getApplicationContext(),
error.getMessage(), Toast.LENGTH_SHORT).show();
}
}) {

@Override
protected Map getParams() {
Map params = new HashMap();
params.put(“otp”, otp);

Log.e(TAG, “Posting params: ” + params.toString());
return params;
}

};

// Adding request to request queue
MyApplication.getInstance().addToRequestQueue(strReq);
}

}

Max Vignesh
Max Vignesh
5 years ago

Hai i want this project..plz someone guide that how to run this project..

Rashid mohammed
Rashid mohammed
5 years ago

Hello Ravi sir. First of all, thank you for providing extremely useful tutorials like this. The codes worked well for me except this problem, every time I register with the app I get OTP twice and the same details are entered twice to the database. The two otps reach my phone almost instantly without any delay. To check the issue, In the request_sms.php file, I removed the function sendSms($mobile, $otp); from the if statement and when I registered with the app, database stores details only once. But when I add sendSms($mobile, $otp); I am getting OTP twice and the user details are entered twice in the database. Sir, please help me in this case. I am just a helpless beginner.

Ravi Tamada
5 years ago

Its due to slow server response. Add the below code in requestForSMS() function.

int socketTimeout = 0;
RetryPolicy policy = new DefaultRetryPolicy(socketTimeout,
DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT);

strReq.setRetryPolicy(policy);

// Adding request to request queue
MyApplication.getInstance().addToRequestQueue(strReq);

Rashid mohammed
Rashid mohammed
5 years ago
Reply to  Ravi Tamada

Thank you very much Ravi sir!
The given code worked perfectly:)

Ravi Tamada
5 years ago

Cheers!

Avinash Kumar
Avinash Kumar
5 years ago

m getting this error in building gradle

Error:(26, 13) Failed to resolve: com.mcxiaoke.volley:library-aar:1.0.0

Rakesh Sahani
Rakesh Sahani
5 years ago
Reply to  Avinash Kumar

same here

Ronnie
Ronnie
5 years ago

Hello, The tutorials are best in the way u have described and I really wanna thank you for the systematic way used for presentation. Unfortunately, I am stuck at the moment. While I enter my details of email , name and phone; I get an error popping out as “java.net.SocketException:socketfailed:EACCES(permission denied)”. I would be deeply obliged to you if u could consider my query and help me with the issue. THanks in advance

sameer khan
sameer khan
4 years ago
Reply to  Ronnie

Try with,

instead of,

and the permission should be before the application tag

Rakesh Sahani
Rakesh Sahani
5 years ago

{“error”:true,”message”:”Sorry! mobile number is not valid or missing.”}

Santhoshkumar
Santhoshkumar
5 years ago

FATAL EXCEPTION: main java.lang.NullPointerException at com.example.inodesys.android_otp.activity.SmsActivity.requestForSMS(SmsActivity.java:254) at com.example.inodesys.android_otp.activity.SmsActivity.validateForm(SmsActivity.java:163) at com.example.inodesys.android_otp.activity.SmsActivity.onClick(SmsActivity.java:123) at android.view.View.performClick(View.java:4421) at android.view.View$PerformClick.run(View.java:17904) at android.os.Handler.handleCallback(Handler.java:730) at android.os.Handler.dispatchMessage(Handler.java:92) at android.os.Looper.loop(Looper.java:137) at android.app.ActivityThread.main(ActivityThread.java:5214) at java.lang.reflect.Method.invokeNative(NativeMethod) at java.lang.reflect.Method.invoke(Method.java:525) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:739) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:555) at dalvik.system.NativeStart.main(Native Method)

Pls clear this eror

Shan Santhoshkumar
Shan Santhoshkumar
5 years ago

E/AndroidRuntime: FATAL EXCEPTION: main
java.lang.NullPointerException
at com.example.inodesys.android_otp.activity.SmsActivity.requestForSMS(SmsActivity.java:254)
at com.example.inodesys.android_otp.activity.SmsActivity.validateForm(SmsActivity.java:163)
at com.example.inodesys.android_otp.activity.SmsActivity.onClick(SmsActivity.java:123)
at android.view.View.performClick(View.java:4421)
at android.view.View$PerformClick.run(View.java:17904)
at android.os.Handler.handleCallback(Handler.java:730)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5214)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:525)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:739)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:555)
at dalvik.system.NativeStart.main(Native Method)

sh.f
sh.f
5 years ago

Hello Mr Ravi

sh.f
sh.f
5 years ago

:disqus

sh.f
sh.f
5 years ago

.

Ishita Sinha
Ishita Sinha
5 years ago

Hi, Sir,

I am new to android. This is a great tutorial and I have been able to implement it fully. I have one small problem, though. On some smaller devices, the soft keyboard hides the EditText views in the ViewPager. Adding adjustResize or adjustPan in the manifest doesn’t seem to work. Please let me know how I can fix this. Thanks.

Ravi Tamada
5 years ago
Reply to  Ishita Sinha

In order to adjustResize work, the parent layout should be RelativeLayout. What is your parent layout?

Ishita Sinha
Ishita Sinha
5 years ago
Reply to  Ravi Tamada

Thank you so much for the quick reply. My parent layout is a RelativeLayout, inside that I have the ViewPager, inside the ViewPager there are two LinearLayouts. Should I change those LinearLayouts to RelativeLayouts?

Ravi Tamada
5 years ago
Reply to  Ishita Sinha

It happens because of lot of factors. Can you try setting adjustPan through code in activity or fragment.

Ishita Sinha
Ishita Sinha
5 years ago
Reply to  Ravi Tamada

Thank you for suggesting this. Apparently the problem was the hard-coded “125dp” as the app icon’s top margin. I changed the LinearLayout’s gravity to be “center_horizontal|center_vertical” and removed the layout_marginTop from the icon’s attributes. Now the keyboard is pushing up the EditTexts as desired, and all the text/images are also centered on the screen. 🙂

Ravi Tamada
5 years ago
Reply to  Ishita Sinha

Cheers!

Abhi Khatua
Abhi Khatua
5 years ago

Hi , sir
i am new to android . just i tried to do as u did above with different layout , as i’m unable to slide page to otp layout ..please help me as i’m trying from last one week .. tried every thing , you are my my last hope . please do suggest so that i can come out of this issue …any suggestion will make my 7 horrible day .. please

private static String TAG = SmsReceiver.class.getSimpleName();

// declaration

private EditText phnum, otp, mob;

private Button cont, act;

private PrefManager pref;

private ProgressBar progressBar;

private RelativeLayout layout_otp;

private ViewPager viewPager;

private ViewPagerAdapter adapter;

private LinearLayout layoutedit;

ImageButton editmobile;

private Toolbar toolbar ;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.verification_mobile);

//initialization

viewPager = (ViewPager) findViewById(R.id.viewPagerVertical);

phnum = (EditText) findViewById(R.id.phnum);

mob = (EditText) findViewById(R.id.mob);

cont = (Button) findViewById(R.id.cont);

otp = (EditText) findViewById(R.id.otp);

act = (Button) findViewById(R.id.act);

layout_otp = (RelativeLayout) findViewById(R.id.layout_otp);

progressBar = (ProgressBar) findViewById(R.id.progressBar);

editmobile = (ImageButton) findViewById(R.id.editmobile);

layoutedit = (LinearLayout) findViewById(R.id.layout_edit_mobile);

toolbar = (Toolbar) findViewById(R.id.back);

//for back button

setSupportActionBar(toolbar);

getSupportActionBar().setHomeButtonEnabled(false);

getSupportActionBar().setDisplayHomeAsUpEnabled(true);

getSupportActionBar().setHomeAsUpIndicator(R.mipmap.ic_navigate_before_white_24dp);

//view click listeners

cont.setOnClickListener(this);

act.setOnClickListener(this);

editmobile.setOnClickListener(this);

//hiding the LayoutEditmobile

layoutedit.setVisibility(View.GONE);

pref = new PrefManager(this);

/**

* checking for user login

* if the user is logging , then will take him to suppliers Activity

*/

if (pref.isLoggedIn()) {

Intent intent = new Intent(VerificationActivity.this, SupplierActivity.class);

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);

startActivity(intent);

finish();

}

adapter = new ViewPagerAdapter();

viewPager.setAdapter(adapter);

viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {

@Override

public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

}

@Override

public void onPageSelected(int position) {

}

@Override

public void onPageScrollStateChanged(int state) {

}

});

/**

* checking if device is waiting for sms

* the show the otp screen

*/

if (pref.isWaitingForSms()) {

viewPager.setCurrentItem(1);

layoutedit.setVisibility(View.VISIBLE);

}

}

@Override

public void onClick(View view) {

switch (view.getId()) {

case R.id.cont:

validateForm();

case R.id.act:

verifyOtp();

break;

case R.id.editmobile:

viewPager.setCurrentItem(0);

layoutedit.setVisibility(View.GONE);

pref.setIsWaitingForSms(false);

break;

}

}

/**

* validating user details

*/

private void validateForm() {

String ph = phnum.getText().toString().trim();

/**

* checking weather the phone number is 10digit or not

*/

if (isValidPhoneNumber(ph)) {

//request for sms

progressBar.setVisibility(View.VISIBLE);

//saving the mobile number in sharedpreferences

pref.setMobileNumber(ph);

//requesting for sms

requestForSMS(ph);

} else {

Toast.makeText(getApplicationContext(), “please enter valid phone number”, Toast.LENGTH_LONG).show();

}

}

/**

* Again creating string request`

*

* @param ph

* @return

*/

private void requestForSMS(final String ph) {

String url = Config.URL_REQUEST_SMS + “?phone=” + ph;

StringRequest strReq = new StringRequest(Request.Method.POST, url, new Response.Listener() {

@Override

public void onResponse(String response) {

Log.d(TAG, response.toString());

try {

//creating json object

JSONObject responseObj = new JSONObject(response);

//Parsing json response

boolean error = responseObj.getBoolean(“error”);

String message = responseObj.getString(“message”);

//checking for error if not error then initialized

if (!error) {

//boolean flag says device is waiting for sms

pref.setIsWaitingForSms(true);

Log.d(TAG, “cntrjkah”);

//moving the screen to next pager item i.e otp screen

viewPager.setCurrentItem(2);

mob.setText(pref.getMobileNumber());

layoutedit.setVisibility(View.VISIBLE);

Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show();

} else {

Toast.makeText(getApplicationContext(), “error:” + message, Toast.LENGTH_LONG).show();

}

//hiding the progressbar

progressBar.setVisibility(View.GONE);

} catch (JSONException e) {

Toast.makeText(getApplicationContext(), “Error:” + e.getMessage(), Toast.LENGTH_LONG).show();

progressBar.setVisibility(View.GONE);

}

}

},

new Response.ErrorListener() {

@Override

public void onErrorResponse(VolleyError error) {

Log.e(TAG, ” Error” + error.getMessage());

Toast.makeText(getApplicationContext(), error.getMessage(), Toast.LENGTH_LONG).show();

}

}) {

/**

* passing user parameter to the server

*/

protected Map getParams() {

Map params = new HashMap();

params.put(“phnum”, ph);

Log.e(TAG, “Posting params:” + params.toString());

return params;

}

};

//Adding request to request queue

MyApplication.getInstance().addToRequestQueue(strReq);

}

/**

* sending the Opt too server and activating the server

*

*/

private void verifyOtp() {

String Otp = otp.getText().toString().trim();

if (!Otp.isEmpty()) {

Intent grapprIntent = new Intent(getApplicationContext(), HttpService.class);

grapprIntent.putExtra(“otp”, Otp);

startService(grapprIntent);

} else {

Toast.makeText(getApplicationContext(), “please provide the otp”, Toast.LENGTH_LONG).show();

}

}

/*

checking weather the user is inputting the number or not

*/

private static boolean isValidPhoneNumber(String mobile) {

String regEx = “^[0-9]{10}$”;

return mobile.matches(regEx);

}

class ViewPagerAdapter extends PagerAdapter {

@Override

public int getCount() {

return 2;

}

@Override

public boolean isViewFromObject(View view, Object object) {

return view == ((View) object);

}

public Object instantiateItem(View collection, int position) {

int resId = 0;

switch (position) {

case 0:

resId = R.id.layout_Sms;

break;

case 1:

resId = R.id.layout_otp;

break;

}

return findViewById(resId);

}

}

@Override

public boolean onOptionsItemSelected(MenuItem item) {

switch (item.getItemId()) {

case android.R.id.home:

Toast.makeText(getApplicationContext(), “Home Clicked”,

Toast.LENGTH_LONG).show();

// go to previous activity

onBackPressed();

return true;

}

return super.onOptionsItemSelected(item);

}

}

Abhijit Das
5 years ago

Hello Ravi,
I have tried implementing the above code and everything works fine except the part where it receives the OTP automatically. I tried looking for the issue and found out that the receiver is never called. TIA

S H
S H
5 years ago

Hello Ravi, instead of msg91 api can i use twilio?

HARDIK AMAL
HARDIK AMAL
5 years ago

Working fine in pre-marshmallow…receiver not working in marshmallow…how do i solve this?

WatsOne
WatsOne
5 years ago
Reply to  HARDIK AMAL

READ_SMS and RECEIVE_SMS permissions are dangerous now in marshmallow. You must use requesting permissions at run time. Check this: http://developer.android.com/intl/ru/training/permissions/requesting.html

Mahesh Kanduri
Mahesh Kanduri
5 years ago

Hi ravi i need help how to do auto verifying the otp code

Ravi Tamada
5 years ago
Reply to  Mahesh Kanduri

If you mean auto matic otp verification? It is already explained.

Legolas
Legolas
5 years ago

Hi, you made a broadcast receiver to check the sms, but is this a good way to do this? I mean the receiver will always check for sms even when you registered , right?

Ravi Tamada
5 years ago
Reply to  Legolas

You need to remove the broadcast receiver once you registered.
http://stackoverflow.com/questions/7439041/how-to-unregister-broadcastreceiver

Legolas
Legolas
5 years ago
Reply to  Ravi Tamada

so why don’t use postdelayed handler only in register activity?

Ravi Kumar
Ravi Kumar
5 years ago

hi , i followed ur tutorial , and i removed name and email id and making it register through just phone number which is working perfectly fine . now i want to create a profile page , in which i want user to allow set their profile . in that they should b able to set profile image and name . and i wanna share that information on database . can u please help . and is their any way to contact u directly

Ashiwani N
Ashiwani N
5 years ago

Everything is working fine but when I’m clicking NEXT then I got the toast message “Error : Value Config.php of type java.lang.String cannot be converted to JSONObject”. This error belongs to SmsActivity when I debugged the project.

Pritam Kumar Shahi
Pritam Kumar Shahi
5 years ago

How to run the php server can anyone help me?

Anchal Singh
Anchal Singh
5 years ago

Everything is working fine but when I’m clicking NEXT then I got the toast message “Error : Value Config.php of type java.lang.String cannot be converted to JSONObject”. This error belongs to SmsActivity when I debugged the project.

Ashiwani N
Ashiwani N
5 years ago
Reply to  Anchal Singh

public void onResponse(String response) {
Log.d(TAG, response.toString());

try {
int pos=response.indexOf(‘{‘);
response=response.substring(pos);
JSONObject responseObj = new JSONObject(response);

// Parsing json object response
// response will be a json object
boolean error = responseObj.getBoolean(“error”);
String message = responseObj.getString(“message”);

// checking for error, if not error SMS is initiated
// device should receive it shortly
if (!error) {
// boolean flag saying device is waiting for sms
pref.setIsWaitingForSms(true);

// moving the screen to next pager item i.e otp screen
viewPager.setCurrentItem(1);
txtEditMobile.setText(pref.getMobileNumber());
layoutEditMobile.setVisibility(View.VISIBLE);

Toast.makeText(getApplicationContext(), message, Toast.LENGTH_SHORT).show();

} else {
Toast.makeText(getApplicationContext(),
“Error: ” + message,
Toast.LENGTH_LONG).show();
}

// hiding the progress bar
progressBar.setVisibility(View.GONE);

} catch (JSONException e) {
Toast.makeText(getApplicationContext(),
“Error: ” + e.getMessage(),
Toast.LENGTH_LONG).show();

progressBar.setVisibility(View.GONE);
}

}

Anchal Singh
Anchal Singh
5 years ago
Reply to  Ashiwani N

Thanks for your valuable support ,the old error has changes to a new one…something like error 404.

Ashiwani N
Ashiwani N
5 years ago
Reply to  Anchal Singh

I think that should be related with server details. If you are using wampserver as localhost check the details you’ve entered in connection.php file (hostname, user,password,databseName) that is present in C:wamp64www

Ashiwani N
Ashiwani N
5 years ago
Reply to  Anchal Singh

Line 4, 5 are added bcoz json object starts n end with braces. Given code is of SmsActivity.java

240
0
Would love your thoughts, please comment.x
()
x