Monday, 25 December 2017

Login With Google Plus In Android Example



 


Full Source Code Download Here:
https://github.com/sanjaymangaroliya/LoginWithGooglePlus


MainActivity.java

package com.sanjay.loginwithgoogleplus;
import android.app.ProgressDialog;
import android.content.Intent;
import android.net.Uri;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.google.android.gms.auth.api.Auth;
import com.google.android.gms.auth.api.signin.GoogleSignInAccount;
import com.google.android.gms.auth.api.signin.GoogleSignInOptions;
import com.google.android.gms.auth.api.signin.GoogleSignInResult;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.OptionalPendingResult;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.common.api.Status;

public class MainActivity extends AppCompatActivity implements
        GoogleApiClient.OnConnectionFailedListener {

    private Button btn_sign_in, btn_logout;
    private ImageView img_profile;
    private TextView tv_info;
    //private SignInButton btn_sign_in_default;
    private static final int RC_SIGN_IN = 100;
    private GoogleApiClient mGoogleApiClient;
    private ProgressDialog progressDialog;

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

        //Toolbar
        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        getSupportActionBar().setDisplayShowTitleEnabled(false);

        GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                .requestEmail()
                .build();
        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .enableAutoManage(this, this)
                .addApi(Auth.GOOGLE_SIGN_IN_API, gso)
                .build();
        // Customizing G+ button
        //btn_sign_in_default.setSize(SignInButton.SIZE_STANDARD);
        //btn_sign_in_default.setScopes(gso.getScopeArray());

        initUI();
    }

    private void initUI() {
        TextView tvTitle = findViewById(R.id.tv_title);
        tvTitle.setText(getResources().getString(R.string.app_name));
        //btn_sign_in_default = findViewById(R.id.btn_sign_in_default);
        btn_sign_in = findViewById(R.id.btn_sign_in);
        btn_logout = findViewById(R.id.btn_logout);
        img_profile = findViewById(R.id.img_profile);
        tv_info = findViewById(R.id.tv_info);
    }

    public void onClickSignIn(View view) {
        if (Utils.isNetworkAvailable(this)) {
            Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
            startActivityForResult(signInIntent, RC_SIGN_IN);
        } else {
            Utils.showAlertDialog(this, getResources().getString(R.string.alert)
                    , getResources().getString(R.string.internet_error));
        }
    }

    private void handleSignInResult(GoogleSignInResult result) {
        if (result.isSuccess()) {
            updateUI(true);
            GoogleSignInAccount acct = result.getSignInAccount();
            String personName = acct.getDisplayName();
            String personEmail = acct.getEmail();
            Uri personPhotoUrl = acct.getPhotoUrl();

            StringBuilder stringBuilder = new StringBuilder();
            if (Utils.isNotEmptyString(personName)) {
                stringBuilder.append("Name: " + personName);
            }
            if (Utils.isNotEmptyString(personEmail)) {
                stringBuilder.append("\nEmail: " + personEmail);
            }
            tv_info.setText(stringBuilder.toString());
            //Profile Picture
            if (personPhotoUrl != null) {
                Glide.with(getApplicationContext()).load(personPhotoUrl)
                        .thumbnail(0.5f)
                        .crossFade()
                        .diskCacheStrategy(DiskCacheStrategy.ALL)
                        .into(img_profile);
            }
        } else {
            updateUI(false);
        }
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == RC_SIGN_IN) {
            GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
            handleSignInResult(result);
        }
    }

    @Override
    public void onStart() {
        super.onStart();
        OptionalPendingResult<GoogleSignInResult> opr = Auth.GoogleSignInApi.silentSignIn(mGoogleApiClient);
        if (opr.isDone()) {
            GoogleSignInResult result = opr.get();
            handleSignInResult(result);
        } else {
            showProgressDialog();
            opr.setResultCallback(new ResultCallback<GoogleSignInResult>() {
                @Override
                public void onResult(GoogleSignInResult googleSignInResult) {
                    hideProgressDialog();
                    handleSignInResult(googleSignInResult);
                }
            });
        }
    }

    @Override
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
    }

    private void showProgressDialog() {
        if (progressDialog == null) {
            progressDialog = new ProgressDialog(this);
            progressDialog.setMessage("Loading...");
            progressDialog.setIndeterminate(true);
        }
        progressDialog.show();
    }

    private void hideProgressDialog() {
        if (progressDialog != null && progressDialog.isShowing()) {
            progressDialog.hide();
        }
    }

    private void updateUI(boolean isSignedIn) {
        if (isSignedIn) {
            btn_sign_in.setVisibility(View.GONE);
            btn_logout.setVisibility(View.VISIBLE);
            img_profile.setVisibility(View.VISIBLE);
            tv_info.setVisibility(View.VISIBLE);
        } else {
            btn_sign_in.setVisibility(View.VISIBLE);
            btn_logout.setVisibility(View.GONE);
            img_profile.setVisibility(View.GONE);
            tv_info.setVisibility(View.GONE);
        }
    }

    public void onClickLogout(View view) {
        if (mGoogleApiClient.isConnected()) {
            Auth.GoogleSignInApi.signOut(mGoogleApiClient).setResultCallback(
                    new ResultCallback<Status>() {
                        @Override
                        public void onResult(Status status) {
                            updateUI(false);
                        }
                    });
        }
    }
}


Utils.java

package com.sanjay.loginwithgoogleplus;
import android.content.Context;
import android.content.DialogInterface;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.support.v7.app.AlertDialog;
import android.view.Gravity;
import android.widget.Toast;

public class Utils {

    public static boolean isNetworkAvailable(Context context) {
        if (context == null) {
            return false;
        }
        ConnectivityManager cm =
                (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
        boolean isConnected = activeNetwork != null &&
                activeNetwork.isConnectedOrConnecting();
        return isConnected;
    }

    public static void showToast(Context activity, String strMsg) {
        Toast toast = Toast.makeText(activity, strMsg, Toast.LENGTH_SHORT);
        toast.setGravity(Gravity.CENTER_HORIZONTAL, 0, 0);
        toast.show();
    }

    public static void showAlertDialog(Context context, String title, String msg) {
        AlertDialog.Builder adb = new AlertDialog.Builder(context);
        adb.setTitle(title);
        adb.setMessage(msg);
        adb.setCancelable(false);
        adb.setPositiveButton("OK", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.dismiss();
            }
        });
        adb.create().show();
    }

    public static boolean isNotEmptyString(String str) {
        if (str != "" && str != null && str.trim().length() > 0
                && !str.equalsIgnoreCase("null")) {
            return true;
        }
        return false;
    }

}


activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/white"
    android:fitsSystemWindows="true">

    <include layout="@layout/toolbar" />

    <android.support.v4.widget.NestedScrollView
        android:id="@+id/nested_scrollview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <RelativeLayout
            android:id="@+id/rl_main"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_margin="10dp">

            <!-- <com.google.android.gms.common.SignInButton
                 android:id="@+id/btn_sign_in_default"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:layout_marginTop="20dp"
                 android:onClick="onClickSignIn"
                 android:visibility="gone" />-->

            <Button
                android:id="@+id/btn_sign_in"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="20dp"
                android:background="@color/colorPrimary"
                android:gravity="center"
                android:onClick="onClickSignIn"
                android:text="@string/sign_in"
                android:textColor="@color/white"
                android:visibility="visible" />

            <Button
                android:id="@+id/btn_logout"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_below="@+id/btn_sign_in"
                android:layout_marginTop="20dp"
                android:background="@color/colorPrimary"
                android:gravity="center"
                android:onClick="onClickLogout"
                android:text="@string/logout"
                android:textColor="@color/white"
                android:visibility="gone" />

            <ImageView
                android:id="@+id/img_profile"
                android:layout_width="80dp"
                android:layout_height="80dp"
                android:layout_alignParentLeft="true"
                android:layout_below="@+id/btn_logout"
                android:layout_marginTop="20dp"
                android:src="@mipmap/ic_launcher"
                android:visibility="gone" />

            <TextView
                android:id="@+id/tv_info"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_below="@+id/btn_logout"
                android:layout_marginLeft="10dp"
                android:layout_marginTop="20dp"
                android:layout_toRightOf="@+id/img_profile"
                android:text="@string/name"
                android:textColor="@color/colorPrimary"
                android:textSize="16dp"
                android:visibility="gone" />
        </RelativeLayout>
    </android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>


toolbar.xml

<android.support.design.widget.AppBarLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/app_bar_layout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:theme="@style/AppTheme.AppBarOverlay">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        app:popupTheme="@style/AppTheme.PopupOverlay">

        <TextView
            android:id="@+id/tv_title"
            style="@style/tv_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/app_name" />
    </android.support.v7.widget.Toolbar>

</android.support.design.widget.AppBarLayout>


AndroidManifest.xml

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

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity
            android:name=".MainActivity"
            android:screenOrientation="portrait">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>


styles.xml

<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimary</item>
        <item name="colorAccent">@color/colorPrimary</item>
        <item name="windowActionBar">true</item>
        <item name="windowNoTitle">true</item>
    </style>

    <style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />

    <style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />

    <style name="tv_title">
        <item name="android:layout_gravity">center</item>
        <item name="android:textColor">@color/white</item>
        <item name="android:textSize">20sp</item>
        <item name="android:textAllCaps">false</item>
        <item name="android:textStyle">normal</item>
    </style>

    <style name="textView">
        <item name="android:singleLine">true</item>
        <item name="android:textAllCaps">false</item>
    </style>

</resources>


build.gradle

apply plugin: 'com.android.application'

android {
    compileSdkVersion 26
    defaultConfig {
        applicationId "com.sanjay.loginwithgoogleplus"
        minSdkVersion 16
        targetSdkVersion 26
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:26.1.0'
    implementation 'com.android.support.constraint:constraint-layout:1.0.2'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.1'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
    //Support Design
    compile 'com.android.support:design:26+'
    //Google Auth
    compile 'com.google.android.gms:play-services-auth:11.8.0'
    //Glide Image
    compile 'com.github.bumptech.glide:glide:3.7.0'

}
apply plugin: 'com.google.gms.google-services'

Login With Facebook In Android Example






Full Source Code Download Here:
https://github.com/sanjaymangaroliya/LoginWithFacebook


MainActivity

package com.sanjay.loginwithfacebook;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.facebook.AccessToken;
import com.facebook.CallbackManager;
import com.facebook.FacebookCallback;
import com.facebook.FacebookException;
import com.facebook.GraphRequest;
import com.facebook.GraphResponse;
import com.facebook.HttpMethod;
import com.facebook.login.LoginManager;
import com.facebook.login.LoginResult;
import com.facebook.login.widget.LoginButton;
import org.json.JSONException;
import org.json.JSONObject;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Arrays;

public class MainActivity extends AppCompatActivity {

    private Button btn_sign_in, btn_logout;
    private ImageView img_profile;
    private TextView tv_info;
    private LoginButton loginButton;
    private CallbackManager callbackManager;

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

        //Toolbar
        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        getSupportActionBar().setDisplayShowTitleEnabled(false);

        callbackManager = CallbackManager.Factory.create();

        initUI();
    }

    private void initUI() {
        TextView tvTitle = findViewById(R.id.tv_title);
        tvTitle.setText(getResources().getString(R.string.app_name));
        btn_sign_in = findViewById(R.id.btn_sign_in);
        btn_logout = findViewById(R.id.btn_logout);
        img_profile = findViewById(R.id.img_profile);
        tv_info = findViewById(R.id.tv_info);
        loginButton = findViewById(R.id.login_button);

        //Default Login Button
       /* loginButton.setReadPermissions("public_profile", "email");
        loginButton.registerCallback(callbackManager, new FacebookCallback<LoginResult>() {
            @Override
            public void onSuccess(LoginResult loginResult) {
                Utils.showToast(MainActivity.this, "Login Successfully.");
                GraphRequest request = GraphRequest.newMeRequest(
                        loginResult.getAccessToken(), new GraphRequest.GraphJSONObjectCallback() {
                            @Override
                            public void onCompleted(JSONObject object, GraphResponse response) {
                                getUserData(object);
                            }
                        });
                Bundle parameters = new Bundle();
                parameters.putString("fields", "id, first_name, last_name, email, gender, birthday, location");
                request.setParameters(parameters);
                request.executeAsync();
            }

            @Override
            public void onCancel() {
                Utils.showToast(MainActivity.this, "Login Cancel.");
                updateUI(false);
            }

            @Override
            public void onError(FacebookException exception) {
                Utils.showToast(MainActivity.this, "Login Error.");
                updateUI(false);
            }
        });*/
    }

    //Custom Login Button
    public void onClickSignIn(View view) {
        if (Utils.isNetworkAvailable(this)) {
            LoginManager.getInstance().logInWithReadPermissions(
                    this, Arrays.asList("public_profile", "email"));

            LoginManager.getInstance().registerCallback(
                    callbackManager, new FacebookCallback<LoginResult>() {
                        @Override
                        public void onSuccess(LoginResult loginResult) {
                            Utils.showToast(MainActivity.this, "Login Successfully.");
                            GraphRequest request = GraphRequest.newMeRequest(
                                    loginResult.getAccessToken(), new GraphRequest.GraphJSONObjectCallback() {
                                        @Override
                                        public void onCompleted(JSONObject object, GraphResponse response) {
                                            getUserData(object);
                                        }
                                    });
                            Bundle parameters = new Bundle();
                            parameters.putString("fields", "id, first_name, last_name, email, gender, birthday, location");
                            request.setParameters(parameters);
                            request.executeAsync();
                        }

                        @Override
                        public void onCancel() {
                            Utils.showToast(MainActivity.this, "Login Cancel.");
                            updateUI(false);
                        }

                        @Override
                        public void onError(FacebookException e) {
                            Utils.showToast(MainActivity.this, "Login Error.");
                            updateUI(false);
                        }
                    });
        } else {
            Utils.showAlertDialog(this, getResources().getString(R.string.alert)
                    , getResources().getString(R.string.internet_error));
        }
    }

    //Get User Profile Information
    private void getUserData(JSONObject object) {
        try {
            updateUI(true);
            StringBuilder stringBuilder = new StringBuilder();
            if (object.has("first_name")) {
                stringBuilder.append("First Name: " + object.getString("first_name"));
            }
            if (object.has("last_name")) {
                stringBuilder.append("\nLast Name: " + object.getString("last_name"));
            }
            if (object.has("email")) {
                stringBuilder.append("\nEmail: " + object.getString("email"));
            }
            if (object.has("gender")) {
                stringBuilder.append("\nGender: " + object.getString("gender"));
            }
            if (object.has("birthday")) {
                stringBuilder.append("\nBirthday: " + object.getString("birthday"));
            }
            if (object.has("location")) {
                stringBuilder.append("\nLocation: " + object.getJSONObject("location").getString("name"));
            }
            tv_info.setText(stringBuilder.toString());

            //Profile Picture
            String id = object.getString("id");
            try {
                URL profile_pic = new URL("https://graph.facebook.com/"
                        + id + "/picture?");
                Glide.with(getApplicationContext()).load(profile_pic.toString())
                        .thumbnail(0.5f)
                        .crossFade()
                        .diskCacheStrategy(DiskCacheStrategy.ALL)
                        .into(img_profile);
            } catch (MalformedURLException e) {
                e.printStackTrace();
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        callbackManager.onActivityResult(requestCode, resultCode, data);
        super.onActivityResult(requestCode, resultCode, data);
    }

    //UpDate UI
    private void updateUI(boolean isSignedIn) {
        if (isSignedIn) {
            btn_sign_in.setVisibility(View.GONE);
            btn_logout.setVisibility(View.VISIBLE);
            img_profile.setVisibility(View.VISIBLE);
            tv_info.setVisibility(View.VISIBLE);
        } else {
            btn_sign_in.setVisibility(View.VISIBLE);
            btn_logout.setVisibility(View.GONE);
            img_profile.setVisibility(View.GONE);
            tv_info.setVisibility(View.GONE);
        }
    }

    //Facebook Logout
    public void onClickLogout(View view) {
        if (AccessToken.getCurrentAccessToken() == null) {
            updateUI(false);
            return;
        }
        new GraphRequest(AccessToken.getCurrentAccessToken(),
                "/me/permissions/", null,
                HttpMethod.DELETE, new GraphRequest
                .Callback() {
            @Override
            public void onCompleted(GraphResponse graphResponse) {
                LoginManager.getInstance().logOut();
                Utils.showToast(MainActivity.this, "Logout Successfully.");
                updateUI(false);
            }
        }).executeAsync();
    }
}


Utils.java

package com.sanjay.loginwithfacebook;
import android.content.Context;
import android.content.DialogInterface;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.support.v7.app.AlertDialog;
import android.view.Gravity;
import android.widget.Toast;

public class Utils {

    public static boolean isNetworkAvailable(Context context) {
        if (context == null) {
            return false;
        }
        ConnectivityManager cm =
                (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
        boolean isConnected = activeNetwork != null &&
                activeNetwork.isConnectedOrConnecting();
        return isConnected;
    }

    public static void showToast(Context activity, String strMsg) {
        Toast toast = Toast.makeText(activity, strMsg, Toast.LENGTH_SHORT);
        toast.setGravity(Gravity.CENTER_HORIZONTAL, 0, 0);
        toast.show();
    }

    public static void showAlertDialog(Context context, String title, String msg) {
        AlertDialog.Builder adb = new AlertDialog.Builder(context);
        adb.setTitle(title);
        adb.setMessage(msg);
        adb.setCancelable(false);
        adb.setPositiveButton("OK", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.dismiss();
            }
        });
        adb.create().show();
    }

    public static boolean isNotEmptyString(String str) {
        if (str != "" && str != null && str.trim().length() > 0
                && !str.equalsIgnoreCase("null")) {
            return true;
        }
        return false;
    }

}


activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/white"
    android:fitsSystemWindows="true">

    <include layout="@layout/toolbar" />

    <android.support.v4.widget.NestedScrollView
        android:id="@+id/nested_scrollview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <RelativeLayout
            android:id="@+id/rl_main"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_margin="10dp">

            <com.facebook.login.widget.LoginButton
                android:id="@+id/login_button"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerHorizontal="true"
                android:layout_marginTop="20dp"
                android:visibility="gone" />

            <Button
                android:id="@+id/btn_sign_in"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="20dp"
                android:background="@color/colorPrimary"
                android:gravity="center"
                android:onClick="onClickSignIn"
                android:text="@string/sign_in"
                android:textColor="@color/white"
                android:visibility="visible" />

            <Button
                android:id="@+id/btn_logout"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_below="@+id/btn_sign_in"
                android:layout_marginTop="20dp"
                android:background="@color/colorPrimary"
                android:gravity="center"
                android:onClick="onClickLogout"
                android:text="@string/logout"
                android:textColor="@color/white"
                android:visibility="gone" />

            <ImageView
                android:id="@+id/img_profile"
                android:layout_width="80dp"
                android:layout_height="80dp"
                android:layout_alignParentLeft="true"
                android:layout_below="@+id/btn_logout"
                android:layout_marginTop="20dp"
                android:src="@mipmap/ic_launcher"
                android:visibility="gone" />

            <TextView
                android:id="@+id/tv_info"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_below="@+id/btn_logout"
                android:layout_marginLeft="10dp"
                android:layout_marginTop="20dp"
                android:layout_toRightOf="@+id/img_profile"
                android:text="@string/name"
                android:textColor="@color/colorPrimary"
                android:textSize="16dp"
                android:visibility="gone" />

        </RelativeLayout>
    </android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>


toolbar.xml

<android.support.design.widget.AppBarLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/app_bar_layout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:theme="@style/AppTheme.AppBarOverlay">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        app:popupTheme="@style/AppTheme.PopupOverlay">

        <TextView
            android:id="@+id/tv_title"
            style="@style/tv_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/app_name" />
    </android.support.v7.widget.Toolbar>

</android.support.design.widget.AppBarLayout>


AndroidManifest.xml

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

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity
            android:name=".MainActivity"
            android:screenOrientation="portrait">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <!--Facebook-->
        <meta-data
            android:name="com.facebook.sdk.ApplicationId"
            android:value="@string/facebook_app_id" />

        <activity
            android:name="com.facebook.FacebookActivity"
            android:configChanges="keyboard|keyboardHidden|screenLayout|screenSize|orientation"
            android:label="@string/app_name" />
        <activity
            android:name="com.facebook.CustomTabActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />

                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />

                <data android:scheme="@string/fb_login_protocol_scheme" />
            </intent-filter>
        </activity>

    </application>
</manifest>


styles.xml

<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimary</item>
        <item name="colorAccent">@color/colorPrimary</item>
        <item name="windowActionBar">true</item>
        <item name="windowNoTitle">true</item>
    </style>

    <style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />

    <style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />

    <style name="tv_title">
        <item name="android:layout_gravity">center</item>
        <item name="android:textColor">@color/white</item>
        <item name="android:textSize">20sp</item>
        <item name="android:textAllCaps">false</item>
        <item name="android:textStyle">normal</item>
    </style>

    <style name="textView">
        <item name="android:singleLine">true</item>
        <item name="android:textAllCaps">false</item>
    </style>

</resources>


build.gradle

apply plugin: 'com.android.application'

android {
    compileSdkVersion 26
    defaultConfig {
        applicationId "com.sanjay.loginwithfacebook"
        minSdkVersion 16
        targetSdkVersion 26
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:26.1.0'
    implementation 'com.android.support.constraint:constraint-layout:1.0.2'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.1'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
    //Support Design
    compile 'com.android.support:design:26+'
    //Facebook
    implementation 'com.facebook.android:facebook-login:[4,5)'
    //Glide Image
    compile 'com.github.bumptech.glide:glide:3.7.0'
}












Monday, 6 November 2017

RecyclerView Android Example


PaymentsHistoryActivity

package com.demo
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import android.view.MenuItem
import android.view.View
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.demo.R
import com.demo.global.Constant
import com.demo.global.Utils
import com.demo.models.CommonModel
import com.demo.models.PaymentsModel
import com.demo.patient.adapters.PaymentsHistoryAdapter
import com.demo.restapi.ApiInterface
import com.demo.restapi.ParseController
import kotlinx.android.synthetic.main.pd_activity_common.*
import kotlinx.android.synthetic.main.toolbar.*
import retrofit2.Response

class PaymentsHistoryActivity : AppCompatActivity() {

    private var intTotal: Int = 0
    private var intPage: Int = 1
    private var type: String = Constant.pay
    private var isLoadMore: Boolean = false
    private val arrayList = ArrayList<PaymentsModel>()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.pd_activity_common)

        //Toolbar
        setSupportActionBar(toolbar)
        supportActionBar!!.setDisplayShowTitleEnabled(false)
        supportActionBar!!.setDisplayHomeAsUpEnabled(true)
        toolbar.title = ""
        tvToolbarTitle.text = getString(R.string.payments_history)

        val bundle = intent.extras
        if (bundle != null && Utils.isNotEmptyString(bundle.getString(Constant.type))) {
            type = Utils.chkStr(bundle.getString(Constant.type))
        }

        initUI()
    }

    private fun initUI() {
        val layoutManager = LinearLayoutManager(this)
        recyclerView.layoutManager = layoutManager
        tvNoDataFound.setOnClickListener { refreshData(true) }

        //Pull down to refresh data
        swpRefLayout.setColorSchemeResources(R.color.colorPrimary)
        swpRefLayout.setOnRefreshListener {
            refreshData(false)
        }

        //Pull up to load more data
        recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
            override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
                val position = layoutManager.findLastCompletelyVisibleItemPosition()
                if (isLoadMore && intTotal != arrayList.size && position == arrayList.size - Constant.loadMore) {
                    isLoadMore = false
                    progressBar.visibility = View.VISIBLE
                    getPaymentHistory(false)
                }
            }
        })

        getPaymentHistory(true)
    }

    private fun getPaymentHistory(showShimmer: Boolean) {
        if (showShimmer) {
            shimmerLayout.visibility = View.VISIBLE
            shimmerLayout.startShimmer()
        }

        val hashMap = HashMap<String, String>()
        hashMap[Constant.type] = type
        hashMap[Constant.page] = intPage.toString()

        val call = ApiInterface.create(this).postMethod(Constant.getPaymentHistory, hashMap)
        ParseController(this, call, false,
            resources.getString(R.string.loading), object : ParseController.ApiCompleteListener {
                override fun <T> onSuccessResponse(jsonResponse: Response<T>) {
                    try {
                        val response = jsonResponse.body() as CommonModel?
                        if (response != null) {
                            val code = Utils.chkStr(response.code)
                            val message = Utils.chkStr(response.message)
                            when (code) {
                                Constant._200 -> {
                                    if (response.data != null && response.data!!.payments != null) {
                                        intTotal = Utils.chkInt(response.data!!.total)
                                        if (response.data!!.payments!!.isNotEmpty()) {
                                            arrayList.addAll(response.data!!.payments!!)
                                            isLoadMore = true
                                            intPage++
                                        }
                                    }
                                }
                                Constant._401 -> Utils.logout(this@PaymentsHistoryActivity, message)
                                else -> Utils.showSnackBar(crLayout, message)
                            }
                        }
                    } catch (e: Exception) {
                        e.printStackTrace()
                    }
                    setData()
                }

                override fun onFailedResponse(statusCode: Int, message: String) {
                    Utils.showSnackBar(crLayout, message)
                    setData()
                }
            })
    }

    private fun setData() {
        //Here all loader hidden and closed
        swpRefLayout.isRefreshing = false
        shimmerLayout.stopShimmer()
        shimmerLayout.visibility = View.GONE
        progressBar.visibility = View.GONE

        //Here shown all payment history
        if (arrayList.isNotEmpty()) {
            recyclerView.visibility = View.VISIBLE
            tvNoDataFound.visibility = View.GONE
            if (recyclerView.adapter == null) {
                recyclerView.adapter = PaymentsHistoryAdapter(this, type, arrayList)
            } else {
                recyclerView.adapter!!.notifyDataSetChanged()
            }
        } else {
            recyclerView.visibility = View.GONE
            tvNoDataFound.visibility = View.VISIBLE
        }
    }

    private fun refreshData(showShimmer: Boolean) {
        intPage = 1
        intTotal = 0
        arrayList.clear()
        if (recyclerView.adapter != null) {
            recyclerView.adapter!!.notifyDataSetChanged()
        }
        getPaymentHistory(showShimmer)
    }

    // Back button
    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        return when (item.itemId) {
            android.R.id.home -> {
                Utils.hideKeyboard(this)
                this.finish()
                true
            }
            else -> super.onOptionsItemSelected(item)
        }
    }
}



PaymentsHistoryAdapter

package com.demo.patient.adapters
import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.widget.PopupMenu
import androidx.recyclerview.widget.RecyclerView
import com.demo.R
import com.demo.global.Constant
import com.demo.global.Utils
import com.demo.models.PaymentsModel
import kotlinx.android.synthetic.main.p_item_payments_history.view.*
import java.util.*

class PaymentsHistoryAdapter(
    private val context: Context,
    private val type: String,
    private val arrayList: ArrayList<PaymentsModel>
) : RecyclerView.Adapter<PaymentsHistoryAdapter.ViewHolder>() {

    inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val view = LayoutInflater.from(parent.context)
            .inflate(R.layout.p_item_payments_history, parent, false)
        return ViewHolder(view)
    }

    @SuppressLint("SetTextI18n")
    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val model = arrayList[position]

        if (model.appointment != null) {
            if (type == Constant.pay) {
                var name = ""
                name = if (model.appointment!!.doctor != null) {
                    Utils.chkStr(model.appointment!!.doctor!!.name)
                } else {
                    Utils.chkStr(model.appointment!!.diagnostics!!.name)
                }
                holder.itemView.tvPaidTo.text = name
            } else {
                //received
                holder.itemView.tvPaidToTitle.text =
                    context.resources.getString(R.string.received_from)
                holder.itemView.tvPaidTo.text = Utils.chkStr(model.appointment!!.patient_name)
            }
        }
        // Amount
        val symbol = Utils.chkStr(model.symbol)
        holder.itemView.tvAmount.text = symbol + Utils.chkStrAndReturnInt(model.amount) + "/-"

        if (Utils.isNotEmptyString(Utils.chkStr(model.refund_amount))) {
            holder.itemView.tvRefunded.visibility = View.GONE
        }

        val txnDate = Utils.chkStr(model.txn_date)
        holder.itemView.tvDateAndTime.text =
            Utils.dateFormat(txnDate, Constant.yyyy_mm_dd_hh_mm_ss, Constant.dd_mm_yyyy_hh_mm_a)

        holder.itemView.imgMoreMenu.setOnClickListener {
            val popup = PopupMenu(context, it)
            popup.menuInflater.inflate(R.menu.poupup_menu, popup.menu)
            popup.menu.findItem(R.id.invoice).isVisible = true

            popup.setOnMenuItemClickListener { item ->
                when (item.title) {
                    context.resources.getString(R.string.invoice) -> {
                        val intent = Intent()
                        intent.setDataAndType(Uri.parse(Utils.chkStr(model.invoice)), "application/pdf")
                        context.startActivity(intent)
                    }
                }
                true
            }
            popup.show()
        }
    }

    override fun getItemCount(): Int {
        return arrayList.size
    }

    override fun getItemId(position: Int): Long {
        return position.toLong()
    }

    override fun getItemViewType(position: Int): Int {
        return position
    }
}



 


PaymentsModel

package com.demo.models

import com.google.gson.annotations.SerializedName
import com.demo.global.Constant

class PaymentsModel {

    @SerializedName(Constant.id)
    var id: String? = null

    @SerializedName(Constant.invoice)
    var invoice: String? = null

    @SerializedName(Constant.symbol)
    var symbol: String? = null

    @SerializedName(Constant.refund_amount)
    var refund_amount: String? = null

    //appointment object
    @SerializedName(Constant.appointment)
    var appointment: Appointment? = null

    class Appointment {
        @SerializedName(Constant.id)
        var id: String? = null

        @SerializedName(Constant.patient_name)
        var patient_name: String? = null

        //doctor object
        @SerializedName(Constant.doctor)
        var doctor: Doctor? = null

        class Doctor {
            @SerializedName(Constant.name)
            var name: String? = null
        }

        //doctor object
        @SerializedName(Constant.diagnostics)
        var diagnostics: Diagnostics? = null

        class Diagnostics {
            @SerializedName(Constant.name)
            var name: String? = null
        }
    }

    //files object
    @SerializedName(Constant.prescriptions)
    var prescriptions: ArrayList<AppointmentModel.PrescriptionModel>? = null

    class Practice {
        @SerializedName(Constant.id)
        var id: String? = null

        @SerializedName(Constant.name)
        var name: String? = null
    }
}

Utils

package com.demo.interfaces

import android.annotation.SuppressLint
import android.app.*
import android.content.*
import android.content.pm.PackageManager
import android.graphics.Bitmap
import android.graphics.Color
import android.location.LocationManager
import android.net.ConnectivityManager
import android.net.Uri
import android.os.Build
import android.os.Handler
import android.provider.Settings
import android.text.Html
import android.text.Spanned
import android.text.TextUtils
import android.text.format.DateFormat
import android.util.Base64
import android.util.Base64.encodeToString
import android.util.Log
import android.util.Patterns
import android.view.Gravity
import android.view.WindowManager
import android.view.inputmethod.InputMethodManager
import android.widget.EditText
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.widget.AppCompatImageView
import androidx.appcompat.widget.AppCompatTextView
import androidx.appcompat.widget.LinearLayoutCompat
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.app.NotificationCompat
import androidx.core.content.ContextCompat
import androidx.core.graphics.drawable.toBitmap
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.bumptech.glide.Priority
import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.request.RequestOptions
import com.google.android.gms.common.ConnectionResult
import com.google.android.gms.common.GoogleApiAvailability
import com.google.android.gms.tasks.OnCompleteListener
import com.google.android.material.snackbar.Snackbar
import com.google.android.material.textfield.TextInputEditText
import com.google.firebase.messaging.FirebaseMessaging
import com.hbb20.CountryCodePicker
import com.demo.R
import com.demo.activities.GetOtpActivity
import com.demo.activities.MainActivity
import com.demo.activities.PreviewImageActivity
import com.demo.doctor.adapters.SingleSelectionAdapter
import com.demo.models.UserModel
import com.demo.models.SpinnerModel
import com.demo.videocall.FBData
import com.demo.videocall.FloatingService
import okhttp3.MediaType
import okhttp3.MultipartBody
import okhttp3.RequestBody
import java.io.ByteArrayOutputStream
import java.io.File
import java.io.UnsupportedEncodingException
import java.text.DecimalFormat
import java.text.ParseException
import java.text.SimpleDateFormat
import java.util.*
import java.util.concurrent.TimeUnit

object Utils {
    var isDebugging = true

    // Get current time and date
    @SuppressLint("SimpleDateFormat")
    fun getCurrentTimeAndDate(inputFormat: String): String {
        if (isNotEmptyString(inputFormat)) {
            val sdf = SimpleDateFormat(inputFormat, Locale.getDefault())
            return sdf.format(Date())
        }
        return ""
    }


    // Date format
    @SuppressLint("SimpleDateFormat")
    fun dateFormat(inputDate: String, inputFormat: String, outputFormat: String): String {
        if (isNotEmptyString(inputDate) && isNotEmptyString(inputFormat) && isNotEmptyString(
                        outputFormat
                )
        ) {
            try {
                var sdf = SimpleDateFormat(inputFormat)
                val newDate = sdf.parse(inputDate)
                sdf = SimpleDateFormat(outputFormat)
                return sdf.format(newDate!!)
            } catch (e: Exception) {
                Log.e("Exception", e.message.toString())
            }
        }
        return ""
    }

    // Format date and time
    @SuppressLint("SimpleDateFormat")
    fun localizedDateFormat(inputDate: String, inputFormat: String): String {
        if (isNotEmptyString(inputDate) && isNotEmptyString(inputFormat)) {
            val sdf = SimpleDateFormat(inputFormat, Locale.ENGLISH)
            sdf.timeZone = TimeZone.getTimeZone("UTC")
            val date = sdf.parse(inputDate)
            sdf.timeZone = TimeZone.getDefault()
            return sdf.format(date!!)
        }
        return ""
    }

    fun simpleDateFormat(date: Date, outputFormat: String): String? {
        val format = SimpleDateFormat(outputFormat, Locale.getDefault())
        return format.format(date)
    }

    // Time stamp to date format
    fun timeStampToDateFormat(inputTimeStamp: String, outputFormat: String): String {
        if (isNotEmptyString(inputTimeStamp) && isNotEmptyString(outputFormat)) {
            val time = inputTimeStamp.toLong()
            val cal = Calendar.getInstance()
            cal.timeInMillis = time * 1000
            return DateFormat.format(outputFormat, cal).toString()
        }
        return ""
    }

    // Get current time stamp
    fun getCurrentTimeStamp(): String {
        //val timeStamp = System.currentTimeMillis() / 1000
        val c = Calendar.getInstance()
        val sdf = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZZZZZ", Locale.ENGLISH)
        //Log.e("TIME", "formatted string: " + sdf.format(c.time))
        return sdf.format(c.time).toString()
    }

    // Get current time stamp
    fun getCarbonToDateTime(carbonString: String): String {
        //val timeStamp = System.currentTimeMillis() / 1000
        val c = Calendar.getInstance()
        val sdf = SimpleDateFormat("yy-MM-dd HH:mm", Locale.ENGLISH)
        Log.e("TIME", "formatted string: " + sdf.format(carbonString))
        return sdf.format(c.time).toString()
    }

    // Compare tow date
    fun compareTowDate(startDate: String, endDate: String, inputFormat: String): Boolean {
        if (isNotEmptyString(startDate) && isNotEmptyString(endDate) && isNotEmptyString(inputFormat)) {
            try {
                @SuppressLint("SimpleDateFormat")
                val formatter = SimpleDateFormat(inputFormat)
                val date1 = formatter.parse(startDate)
                val date2 = formatter.parse(endDate)
                if (date1!! < date2) {
                    return true
                }
            } catch (e1: ParseException) {
                e1.printStackTrace()
            }
        }
        return false
    }

    // Format UTC time zone
    @SuppressLint("SimpleDateFormat")
    fun formatUtcTimeZone(inputDate: String, inputFormat: String): String? {
        if (isNotEmptyString(inputDate) && isNotEmptyString(inputFormat)) {
            var convertTime = ""
            try {
                val dateFormat = SimpleDateFormat(inputFormat)
                dateFormat.timeZone = TimeZone.getTimeZone("UTC")
                val pastTime = dateFormat.parse(inputDate)
                val currentTime = Date()
                val dateDiff = currentTime.time - pastTime!!.time
                val second = TimeUnit.MILLISECONDS.toSeconds(dateDiff)
                val minute = TimeUnit.MILLISECONDS.toMinutes(dateDiff)
                val hour = TimeUnit.MILLISECONDS.toHours(dateDiff)
                val day = TimeUnit.MILLISECONDS.toDays(dateDiff)
                when {
                    second < 60 -> //convertTime = second.toString() + "s " + suffix
                        convertTime = "just now"
                    minute < 60 -> convertTime = minute.toString() + "m"
                    hour < 24 -> convertTime = hour.toString() + "hr"
                    day >= 7 -> convertTime = when {
                        day > 30 -> (day / 30).toString() + "mo"
                        day > 360 -> (day / 360).toString() + "y"
                        else -> (day / 7).toString() + "w"
                    }
                    day < 7 -> convertTime = day.toString() + "d"
                }
                return convertTime
            } catch (e: ParseException) {
                e.printStackTrace()
            }
        }
        return ""
    }

    // Format number
    fun formatNumber(value: Long?): String {
        if (value != null) {
            val suffixes = TreeMap<Long, String>()
            suffixes[1_000L] = "K"
            suffixes[1_000_000L] = "M"
            suffixes[1_000_000_000L] = "G"
            suffixes[1_000_000_000_000L] = "T"
            suffixes[1_000_000_000_000_000L] = "P"
            suffixes[1_000_000_000_000_000_000L] = "E"
            //Long.MIN_VALUE == -Long.MIN_VALUE so we need an adjustment here
            if (value == java.lang.Long.MIN_VALUE) return formatNumber(java.lang.Long.MIN_VALUE + 1)
            if (value < 0) return "-" + formatNumber(-value)
            if (value < 1000) return value.toString() //deal with easy case

            val e = suffixes.floorEntry(value)
            val divideBy = e!!.key
            val suffix = e.value

            val truncated = value / (divideBy!! / 10) //the number part of the output times 10
            val hasDecimal = truncated < 100 && truncated / 10.0 != (truncated / 10).toDouble()
            return if (hasDecimal) (truncated / 10.0).toString() + suffix else (truncated / 10).toString() + suffix
        }
        return ""
    }

    // Save preferences data
    fun saveData(context: Context?, key: String, value: String) {
        if (context != null && isNotEmptyString(key) && isNotEmptyString(value)) {
            val preferences =
                    context.getSharedPreferences(Constant.preference, Context.MODE_PRIVATE)
            preferences.edit().putString(key, value).apply()
        }
    }

    // Get preferences data
    fun getData(context: Context?, strKey: String): String {
        if (context != null && isNotEmptyString(strKey)) {
            val preferences =
                    context.getSharedPreferences(Constant.preference, Context.MODE_PRIVATE)
            return preferences.getString(strKey, "")!!
        }
        return ""
    }

    // Remove single preferences data
    fun removeData(context: Context?, key: String) {
        if (context != null && isNotEmptyString(key)) {
            val preferences =
                    context.getSharedPreferences(Constant.preference, Context.MODE_PRIVATE)
            preferences.edit().remove(key).apply()
        }
    }

    // Remove all preferences data
    private fun removeAllData(context: Context?) {
        if (context != null) {
            FBData.setOfflineUser()
            context.stopService(Intent(context, FloatingService::class.java))
            val preferences =
                    context.getSharedPreferences(Constant.preference, Context.MODE_PRIVATE)
            preferences.edit().clear().apply()

        }
    }

    // Check internet connection
    fun isNetworkAvailable(context: Context?): Boolean {
        if (context != null) {
            val cm = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
            val activeNetwork = cm.activeNetworkInfo
            return if (activeNetwork != null) {
                when (activeNetwork.type) {
                    ConnectivityManager.TYPE_WIFI -> true
                    ConnectivityManager.TYPE_MOBILE -> true
                    else -> false
                }
            } else {
                false
            }
        }
        return false
    }

    // Check GPS status
    fun isGPSOn(context: Context?): Boolean {
        if (context != null) {
            val manager = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager
            return manager.isProviderEnabled(LocationManager.GPS_PROVIDER)
        }
        return false
    }

    // Check email validation
    fun isValidEmail(email: String): Boolean {
        if (isNotEmptyString(email)) {
            return (Patterns.EMAIL_ADDRESS.matcher(email).matches())
        }
        return false
    }

    // Check password validation
    fun isValidPassword(password: String?): Boolean {
        if (isNotEmptyString(password)) {
            password?.let {
                val passwordPattern = "^(?=.*[0-9])(?=.*[a-z])(?=.*[@#$%^&+=])(?=\\S+$).{4,}$"
                val passwordMatcher = Regex(passwordPattern)
                return passwordMatcher.find(password) != null
            }
            return false
        }
        return false
    }

    // Check phone number validation
    fun isValidPhone(str: String): Boolean {
        return (!TextUtils.isEmpty(str) && Patterns.PHONE.matcher(str).matches())
    }

    // Get device unique id
    @SuppressLint("HardwareIds")
    fun getDeviceUniqueId(context: Context?): String {
        if (context != null) {
            return Settings.Secure.getString(context.contentResolver, Settings.Secure.ANDROID_ID)
        }
        return ""
    }

    // Get device name, os, sdk version
    fun getDeviceOs(): String {
        val builder = StringBuilder()
        builder.append("Android : ").append(Build.VERSION.RELEASE)
        val fields = Build.VERSION_CODES::class.java.fields
        for (field in fields) {
            val fieldName = field.name
            var fieldValue = -1
            try {
                fieldValue = field.getInt(Any())
            } catch (e: IllegalArgumentException) {
                e.printStackTrace()
            } catch (e: IllegalAccessException) {
                e.printStackTrace()
            } catch (e: NullPointerException) {
                e.printStackTrace()
            }
            if (fieldValue == Build.VERSION.SDK_INT) {
                builder.append(" : ").append(fieldName).append(" : ")
                builder.append("sdk=").append(fieldValue)
            }
        }
        return builder.toString()
    }


    // Check string empty or not
    fun isNotEmptyString(str: String?): Boolean {
        return str != null && str.trim().isNotEmpty() && !str.equals("null", ignoreCase = true)
    }

    // Check string empty or not
    fun isEmptyString(str: String?): Boolean {
        if (str == null || str.trim().isEmpty() || str.equals("null", ignoreCase = true)) {
            return true
        }
        return false
    }

    // Check string empty or not and return String
    fun chkStr(str: String?): String {
        if (str != null && str.isNotEmpty() && !str.equals("null", ignoreCase = true)) {
            return str
        }
        return ""
    }

    // Check string empty or not and return dash String
    fun chkStrAndReturnDash(str: String?): String {
        if (str != null && str.isNotEmpty() && !str.equals("null", ignoreCase = true)) {
            return str
        }
        return "-"
    }

    // Check string empty or not and return Int
    fun chkStrAndReturnInt(str: String?): Int {
        if (str != null && str.isNotEmpty() && !str.equals("null", ignoreCase = true)) {
            return str.toInt()
        }
        return 0
    }

    // Check string empty or not and return float value
    fun chkStrAndReturnFloat(str: String?): Float {
        if (str != null && str.isNotEmpty() && !str.equals("null", ignoreCase = true)) {
            return str.toFloat()
        }
        return 0.0f
    }

    // Check string empty or not and return Double value
    fun chkStrAndReturnDouble(str: String?): Double {
        if (str != null && str.isNotEmpty() && !str.equals("null", ignoreCase = true) && str.trim()
                        .isNotEmpty()
        ) {
            return str.toDouble()
        }
        return 0.0
    }

    // Check string empty or not and return Long value
    fun chkStrAndReturnLong(str: String?): Long {
        if (str != null && str.isNotEmpty() && !str.equals("null", ignoreCase = true) && str.trim()
                        .isNotEmpty()
        ) {
            return str.toLong()
        }
        return 0L
    }

    // Check parameter null or not and return
    fun chkInt(int: Int?): Int {
        if (int != null && int != 0) {
            return int
        }
        return 0
    }

    fun startActivity(context: Context?, activity: Class<*>) {
        context!!.startActivity(Intent(context, activity))
    }

    // Show SnackBar
    fun showSnackBar(coordinatorLayout: CoordinatorLayout?, strMsg: String) {
        if (coordinatorLayout != null && isNotEmptyString(strMsg)) {
            val snackbar = Snackbar.make(coordinatorLayout, strMsg, Snackbar.LENGTH_LONG)
            val sbView = snackbar.view
            val textView = sbView.findViewById<TextView>(R.id.snackbar_text)
            textView.setTextColor(Color.WHITE)
            snackbar.show()
        }
    }

    // Show toast
    fun showToast(context: Context?, strMsg: String) {
        if (context != null && isNotEmptyString(strMsg)) {
            val toast = Toast.makeText(context, strMsg, Toast.LENGTH_SHORT)
            toast.setGravity(Gravity.BOTTOM or Gravity.CENTER_HORIZONTAL, 0, 0)
            toast.show()
        }
    }

    // Show long toast
    fun showToastLong(context: Context?, strMsg: String, timeInSecond: Int) {
        if (context != null && isNotEmptyString(strMsg) && timeInSecond > 0) {
            val toast = Toast.makeText(context, strMsg, Toast.LENGTH_SHORT)
            toast.setGravity(Gravity.CENTER_HORIZONTAL, 0, 0)
            toast.show()
            val handler = Handler()
            handler.postDelayed({ toast.cancel() }, timeInSecond.toLong())
        }
    }

    // Show alert dialog with click listener
    fun showAlertDialog(
            context: Context?,
            title: String,
            message: String,
            onClickListener: DialogInterface.OnClickListener
    ) {
        if (context != null && isNotEmptyString(message)) {
            val builder = AlertDialog.Builder(context)
            if (isNotEmptyString(title)) {
                builder.setTitle(title)
            }
            builder.setMessage(message)
            // builder.setIcon(android.R.drawable.ic_dialog_alert)
            builder.setCancelable(false)
            builder.setPositiveButton(R.string.ok, onClickListener)
            builder.create().show()
        }
    }

    // Show alert dialog
    fun showAlertDialog(context: Context?, title: String, message: String) {
        if (context != null && isNotEmptyString(message)) {
            val builder = AlertDialog.Builder(context)
            if (isNotEmptyString(title)) {
                builder.setTitle(title)
            }
            builder.setMessage(message)
            builder.setCancelable(false)
            builder.create().show()
        }
    }

    // Hide keyboard
    fun hideKeyboard(context: Context?) {
        if (context != null) {
            val view = (context as Activity).currentFocus
            if (view != null) {
                val inputManager =
                        context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
                inputManager.hideSoftInputFromWindow(
                        view.windowToken,
                        InputMethodManager.HIDE_NOT_ALWAYS
                )
            }
        }
    }

    // Html format
    fun htmlFormat(str: String): Spanned {
        if (isNotEmptyString(str)) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                return Html.fromHtml(str, Html.FROM_HTML_MODE_LEGACY)
            } else {
                @Suppress("DEPRECATION")
                return Html.fromHtml(str)
            }
        }
        @Suppress("DEPRECATION")
        return Html.fromHtml("")
    }

    // Set text color
    fun setTextColor(str: String, color: Int): String {
        return "<font color=$color>$str</font>"
    }

    // Base 64 encode
    fun base64Encode(str: String): String {
        if (isNotEmptyString(str)) {
            try {
                val data = str.toByteArray(charset("UTF-8"))
                return encodeToString(data, Base64.DEFAULT)
            } catch (e: UnsupportedEncodingException) {
                e.printStackTrace()
            }
        }
        return ""
    }

    // Open url in browser
    fun openUrl(context: Context?, str: String) {
        if (context != null && isNotEmptyString(str)) {
            var url = str
            if (!url.startsWith("http://") && !url.startsWith("https://"))
                url = "http://$url"
            val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
            context.startActivity(intent)
        }
    }

    // Open play store as per package name
    fun openPlayStore(context: Context?, appPackageName: String) {
        if (context != null && isNotEmptyString(appPackageName)) {
            try {
                context.startActivity(
                        Intent(
                                Intent.ACTION_VIEW,
                                Uri.parse("market://details?id=$appPackageName")
                        )
                )
            } catch (a: ActivityNotFoundException) {
                context.startActivity(
                        Intent(
                                Intent.ACTION_VIEW,
                                Uri.parse("https://play.google.com/store/apps/details?id=$appPackageName")
                        )
                )
            }
        }
    }

    // Convert bitmap to string
    fun bitmapToString(bmp: Bitmap?): String {
        if (bmp != null) {
            val baos = ByteArrayOutputStream()
            bmp.compress(Bitmap.CompressFormat.JPEG, 100, baos)
            val imageBytes = baos.toByteArray()
            return encodeToString(imageBytes, Base64.DEFAULT)
        }
        return ""
    }

    // Bold and not text single line
    fun boldNormalText(str1: String, str2: String): String {
        return if (isNotEmptyString(str1) && isNotEmptyString(str2)) "<b>$str1</b>$str2" else ""
    }

    // Hide status bar
    fun hideStatusBar(activity: Activity?) {
        activity?.window?.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN)
    }

    // Status bar color
    fun statusBarColor(activity: Activity?, color: Int) {
        if (activity != null && color != 0) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                activity.window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
                activity.window.statusBarColor = ContextCompat.getColor(activity, color)
            }
        }
    }

    // Status bar color
    fun transparentBottomMenu(activity: Activity?) {
        activity!!.window.setFlags(
                WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
                WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
        )
    }

    // Create body
    fun createBody(str: String): RequestBody {
        return RequestBody.create(MediaType.parse("text/plain"), str)
    }

    // Create multipart
    fun createMultiPart(filePath: File?, key: String): MultipartBody.Part {
        if (filePath!!.exists()) {
            val body = RequestBody.create(MediaType.parse("multipart/form-data"), filePath)
            return MultipartBody.Part.createFormData(key, "file", body)
        }
        val body = RequestBody.create(MediaType.parse("text/plain"), "")
        return MultipartBody.Part.createFormData(key, "", body)
    }

    // Blank image pass in retrofit api
    fun blankImage(parameter: String): MultipartBody.Part {
        val requestFile = RequestBody.create(MediaType.parse("text/plain"), "")
        return MultipartBody.Part.createFormData(parameter, "", requestFile)
    }

    // Copy text
    fun copyText(context: Context?, str: String) {
        if (context != null && isNotEmptyString(str)) {
            val clipboard = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager?
            val clip = ClipData.newPlainText("Copy", str)
            clipboard?.setPrimaryClip(clip)
        }
    }

    // Show image in ImageView
    fun displayImage(
            context: Context?,
            path: String,
            imageView: AppCompatImageView?,
            defaultImage: Int
    ) {
        if (context != null && imageView != null) {
            val options = RequestOptions().centerCrop().placeholder(defaultImage)
                    .error(defaultImage).diskCacheStrategy(DiskCacheStrategy.ALL)
                    .priority(Priority.HIGH)
            Glide.with(context).load(path).apply(options).into(imageView)

        }
    }

    // preview Image
    fun previewImage(context: Context?, imageUrl: String) {
        if (context != null && isNotEmptyString(imageUrl)) {
            val intent = Intent(context, PreviewImageActivity::class.java)
            intent.putExtra(Constant.profile_picture, imageUrl)
            context.startActivity(intent)
        }
    }

    // Convert string to decimal
    fun stringToDecimal(str: String, pattern: String): String {
        if (isNotEmptyString(str) && isNotEmptyString(pattern)) {
            val precision = DecimalFormat(pattern)
            return precision.format(str.toDouble())
        }
        return ""
    }

    // All letter capital
    fun upperCaseLtr(str: String): String {
        if (isNotEmptyString(str)) {
            return str.toUpperCase(Locale.ROOT)
        }
        return ""
    }

    // All letter small
    fun lowerCaseLtr(str: String): String {
        if (isNotEmptyString(str)) {
            return str.toLowerCase(Locale.ROOT)
        }
        return ""
    }

    // Camel case letter
    fun camelCaseLtr(str: String): String {
        if (isNotEmptyString(str)) {
            return str.substring(0, 1).toUpperCase(Locale.ROOT) + str.substring(1)
        }
        return ""
    }

    fun removeLastChar(str: String, count: Int): String {
        if (isNotEmptyString(str)) {
            return str.substring(0, str.length - count)
        }
        return ""
    }

    // Check google play service available
    fun isGooglePlayServicesAvailable(context: Context?): Boolean {
        if (context != null) {
            val googleApiAvailability = GoogleApiAvailability.getInstance()
            val status = googleApiAvailability.isGooglePlayServicesAvailable(context)
            if (status != ConnectionResult.SUCCESS) {
                if (googleApiAvailability.isUserResolvableError(status)) {
                    googleApiAvailability.getErrorDialog(context as Activity?, status, 2404).show()
                }
                return false
            }
            return true
        }
        return false
    }

    // Check app install or not by package name
    fun isAppInstalled(context: Context?, packageName: String): Boolean {
        if (context != null && isNotEmptyString(packageName)) {
            return try {
                context.packageManager.getApplicationInfo(packageName, 0)
                true
            } catch (e: PackageManager.NameNotFoundException) {
                false
            }
        }
        return false
    }

    // Check abusive words
    fun checkAbusiveWords(text: String): Boolean {
        /*if (isNotEmptyString(text)) {
            val regex = Regex("[^A-Za-z ]")
            val result = regex.replace(text, "")
            val split = result.split(" ")
            for (word in split) {
                if (word.trim().toLowerCase()
                        .matches(Constant.abusiveWords.trim().toLowerCase().toRegex())
                ) {
                    return true
                }
            }
            return false
        }*/
        return false
    }

    // Encrypt String
    fun encryptString(message: String): String {
        return ""
    }

    // Decrypt String
    fun decryptString(message: String): String {
        return ""
    }

    fun compareTime(startTime: String, endtime: String): Boolean {
        val pattern = "HH:mm"
        val sdf = SimpleDateFormat(pattern)
        try {
            val date1 = sdf.parse(startTime)
            val date2 = sdf.parse(endtime)
            return date1.before(date2)
        } catch (e: ParseException) {
            e.printStackTrace()
        }
        return false
    }

    fun showSingleSelectionDialog(
            context: Context,
            editText: EditText,
            arrayList: ArrayList<SpinnerModel>?
    ): Dialog {
        hideKeyboard(context)
        val dialog = Dialog(context)
        dialog.setCancelable(true)
        //dialog.requestWindowFeature(Window.FEATURE_NO_TITLE)
        dialog.window!!.setContentView(R.layout.dialog_single_selection)

        val tvTitle = dialog.findViewById(R.id.tvTitle) as AppCompatTextView
        val llSearch = dialog.findViewById(R.id.llSearch) as LinearLayoutCompat
        val etSearch = dialog.findViewById(R.id.etSearch) as EditText
        val imgClear = dialog.findViewById(R.id.imgClear) as AppCompatImageView
        val recyclerView = dialog.findViewById(R.id.recyclerView) as RecyclerView
        val tvNoDataFound = dialog.findViewById(R.id.tvNoDataFound) as AppCompatTextView
        val tvCancel = dialog.findViewById(R.id.tvCancel) as AppCompatTextView

        val selectedCountry = SpinnerModel()

        val adapter = SingleSelectionAdapter(
                context,
                editText,
                arrayList!!,
                llSearch,
                etSearch,
                tvNoDataFound,
                dialog,
                imgClear
        )

        recyclerView.layoutManager = LinearLayoutManager(context)
        recyclerView.adapter = adapter

        tvCancel.setOnClickListener {
            hideKeyboard(context)
            dialog.cancel()
        }

        dialog.setOnDismissListener {
            hideKeyboard(context)
            dialog.cancel()
        }

        dialog.setOnCancelListener {
            hideKeyboard(context)
            dialog.cancel()
        }

        editText.isFocusableInTouchMode = false
        editText.isCursorVisible = false
        editText.setOnClickListener {
            if (arrayList!!.isNotEmpty()) {
                dialog.show()
            }
        }
        return dialog
    }

    fun showSettingsDialog(activity: Activity?) {
        if (activity != null) {
            val builder = android.app.AlertDialog.Builder(activity)
            builder.setTitle(activity.getString(R.string.need_permissions))
            builder.setMessage(activity.getString(R.string.this_app_needs_permission))
            builder.setPositiveButton(activity.getString(R.string.goto_settings)) { dialog, _ ->
                dialog.cancel()
                val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
                val uri = Uri.fromParts("package", activity.packageName, null)
                intent.data = uri
                activity.startActivityForResult(intent, Constant.RC_PERMISSION)
            }
            builder.setNegativeButton(activity.getString(R.string.cancel)) { dialog, _ -> dialog.cancel() }
            builder.show()
        }
    }

    fun savePushToken(context: Context?) {
        FirebaseMessaging.getInstance().token.addOnCompleteListener(OnCompleteListener { task ->
            if (!task.isSuccessful) {
                return@OnCompleteListener
            }
            // Get new FCM registration token
            val token = task.result
            if (isNotEmptyString(token)) {
                saveData(context, Constant.push_token, token.toString().trim())
            }
        })
    }
    
    /* fun specialityWithComma(model: ProfileModel.Detail?): String {
         if (model?.specialties != null && model.specialties!!.isNotEmpty()) {
             val strBuilder = StringBuilder()
             var comma = ""
             for (speciality in model.specialties!!) {
                 strBuilder.append(comma)
                 strBuilder.append(chkStr(speciality.title))
                 comma = ", "
             }
             return strBuilder.toString()
         }
         return ""
     }*/

    fun totalExperience(context: Context?, experience: Int): String {
        if (context != null) {
            return context.resources.getQuantityString(
                    R.plurals.yearCount,
                    experience,
                    experience
            ) + " " +
                    context.resources.getString(R.string.experience)
        }
        return ""
    }

    fun totalDoctor(context: Context?, doctor: Int): String {
        if (context != null) {
            return context.resources.getQuantityString(
                    R.plurals.doctorCount,
                    doctor,
                    doctor
            )
        }
        return ""
    }

    fun totalReview(context: Context?, review: Int): String {
        if (context != null) {
            return context.resources.getQuantityString(R.plurals.reviewCount, review, review)
        }
        return ""
    }

    fun getUserCountry(context: Context?): String {
        val ccp = CountryCodePicker(context)
        ccp.setCountryForPhoneCode(getData(context, Constant.dialcode).toInt())
        return ccp.selectedCountryName
    }

    fun callDial(context: Context?, number: String) {
        if (context != null && isNotEmptyString(number)) {
            val intent = Intent(Intent.ACTION_DIAL)
            intent.data = Uri.parse("tel:$number")
            context.startActivity(intent)
        }
    }

    fun sendEmail(context: Context?, emailId: String, subject: String) {
        if (context != null && isNotEmptyString(emailId)) {
            val uri = Uri.fromParts("mailto", emailId, null)
            val intent = Intent(Intent.ACTION_SENDTO, uri)
            intent.putExtra(Intent.EXTRA_SUBJECT, subject)
            intent.putExtra(Intent.EXTRA_TEXT, "Body")
            context.startActivity(Intent.createChooser(intent, "Send email..."))
        }
    }

    @SuppressLint("SimpleDateFormat")
    fun getTimes(start: String, end: String, interval: Int): ArrayList<String> {
        val sdf1: java.text.DateFormat = SimpleDateFormat("HH:mm")
        try {
            val date: Date = sdf1.parse(start)
            //println("Date and Time: $date")
            val date1: Date = sdf1.parse(end)
            //println("Date and Time1: $date1")
            val times = ArrayList<String>()
            val sdf = SimpleDateFormat("HH:mm")
            val calendar = GregorianCalendar.getInstance()
            calendar.time = date
            if (calendar.time.before(date1)) {
                times.add(sdf.format(calendar.time))
                while (calendar.time.before(date1)) {
                    calendar.add(Calendar.MINUTE, interval)
                    times.add(sdf.format(calendar.time))
                }
            }
            if (times.size > 0) {
                times.removeAt((times.size - 1))
            }
            Log.e("TIMES ", times.toString())
            return times
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return ArrayList<String>()
    }
}


ApiInterface

package com.demo.restapi
import android.content.Context
import android.util.Log
import com.demo.global.Constant
import com.demo.global.Utils
import com.demo.models.CommonModel
import com.readystatesoftware.chuck.ChuckInterceptor
import okhttp3.MultipartBody
import okhttp3.OkHttpClient
import okhttp3.RequestBody
import retrofit2.Call
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.http.*
import java.security.SecureRandom
import java.security.cert.CertificateException
import java.security.cert.X509Certificate
import java.util.concurrent.TimeUnit
import javax.net.ssl.SSLContext
import javax.net.ssl.TrustManager
import javax.net.ssl.X509TrustManager

interface ApiInterface {

    @GET
    fun getMethod(@Url url: String): Call<CommonModel>

    @FormUrlEncoded
    @POST
    fun postMethod(@Url url: String, @FieldMap params: HashMap<String, String>): Call<CommonModel>

    @Multipart
    @POST
    fun uploadFileData(
        @Url url: String,
        @PartMap params: HashMap<String, RequestBody>,
        @Part files: ArrayList<MultipartBody.Part>
    ): Call<CommonModel>

    companion object {
        fun create(context: Context): ApiInterface {
            val retrofit = Retrofit.Builder()
                .client(okHttpClient(context))
                //.client(getUnsafeOkHttpClient(context)!!.build())
                .baseUrl(Constant.baseUrl)
                .addConverterFactory(GsonConverterFactory.create())
                .build()
            return retrofit.create(ApiInterface::class.java)
        }

        //WITH SSL (HTTPS Secure)
        private fun okHttpClient(context: Context): OkHttpClient {
            return OkHttpClient.Builder()
                .connectTimeout(60, TimeUnit.SECONDS)
                .readTimeout(60, TimeUnit.SECONDS)
                .writeTimeout(60, TimeUnit.SECONDS)
                .addInterceptor(ChuckInterceptor(context))
                .addInterceptor { chain ->
                    val newRequest = chain.request().newBuilder()
                        .addHeader("Accept", "application/json")
                        .addHeader("Content-Type", "application/json")
                        .addHeader("Authorization", Utils.getData(context, Constant.token))
                        .build()
                    Log.e("Token", Utils.getData(context, Constant.token))
                    chain.proceed(newRequest)
                }.build()
        }

        //Without SSL (HTTP UnSecure)
        private fun getUnsafeOkHttpClient(context: Context): OkHttpClient.Builder? {
            return try {
                // Create a trust manager that does not validate certificate chains
                val trustAllCerts = arrayOf<TrustManager>(
                    object : X509TrustManager {
                        @Throws(CertificateException::class)
                        override fun checkClientTrusted(
                            chain: Array<X509Certificate>,
                            authType: String
                        ) {
                        }

                        @Throws(CertificateException::class)
                        override fun checkServerTrusted(
                            chain: Array<X509Certificate>,
                            authType: String
                        ) {
                        }

                        override fun getAcceptedIssuers(): Array<X509Certificate> {
                            return arrayOf()
                        }
                    }
                )

                // Install the all-trusting trust manager
                val sslContext = SSLContext.getInstance("SSL")
                sslContext.init(null, trustAllCerts, SecureRandom())
                // Create an ssl socket factory with our all-trusting manager
                val sslSocketFactory = sslContext.socketFactory
                val builder = OkHttpClient.Builder()
                    .connectTimeout(60, TimeUnit.SECONDS)
                    .readTimeout(60, TimeUnit.SECONDS)
                    .writeTimeout(60, TimeUnit.SECONDS)
                    .addInterceptor(ChuckInterceptor(context))
                builder.addInterceptor { chain ->
                    val newRequest = chain.request().newBuilder()
                        .addHeader("Accept", "application/json")
                        .addHeader("Content-Type", "application/json")
                        .addHeader("Authorization", Utils.getData(context, Constant.token))
                        .build()
                    Log.e("Token", Utils.getData(context, Constant.token))
                    chain.proceed(newRequest)
                }.build()
                builder.sslSocketFactory(sslSocketFactory, trustAllCerts[0] as X509TrustManager)
                builder.hostnameVerifier { hostname, session -> true }
                builder
            } catch (e: Exception) {
                throw RuntimeException(e)
            }
        }
    }
}


ParseController

package com.demo.restapi

import android.content.Context
import android.os.Build
import android.util.Log
import androidx.multidex.BuildConfig
import com.nchealthhub.R
import com.google.gson.Gson
import com.demo.global.Constant
import com.demo.global.Utils
import okio.Buffer
import org.json.JSONException
import org.json.JSONObject
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import java.io.IOException
import java.net.URLDecoder

class ParseController(
    private val mContext: Context?, call: Call<*>,
    private val isShowLoading: Boolean,
    private val loadingMsg: String,
    private val listener: ApiCompleteListener
) {
    init {
        if (Utils.isDebugging) {
            Log.e("URL", URLDecoder.decode(call.request().url().toString(), "UTF-8"))
            Log.e("METHOD", URLDecoder.decode(call.request().method().toString(), "UTF-8"))
            if (call.request().body() != null) {
                val buffer = Buffer()
                call.request().body()!!.writeTo(buffer)
                val items = buffer.readUtf8().split("&")
                for (item in items) {
                    Log.e("PARAMETER", item.trim())
                }
            }
        }
        //Api call
        if (loadingMsg != mContext!!.getString(R.string.search)) {
            Utils.hideKeyboard(mContext)
        }
        if (Utils.isNetworkAvailable(mContext)) {
            callRetrofitApi(call)
        } else {
            listener.onFailedResponse(0, mContext!!.getString(R.string.internet_error))
        }
    }

    private fun <T> callRetrofitApi(call: Call<T>) {
        val dialog = CustomDialog(mContext)
        if (isShowLoading) {
            dialog.setCancelable(false)
            dialog.show()
        }
        call.enqueue(object : Callback<T> {
            override fun onResponse(call: Call<T>, response: Response<T>) {
                if (dialog.isShowing) {
                    dialog.dismiss()
                }

                if (response.isSuccessful && response.body() != null && response.body()!!.toString()
                        .trim().isNotEmpty()
                ) {
                    if (Utils.isDebugging) {
                        Log.e("SUCCESSFUL RESPONSE", "" + Gson().toJson(response.body()))
                    }
                    listener.onSuccessResponse(response)
                } else {
                    if (Utils.isDebugging) {
                        Log.e("ERROR RESPONSE", "" + Gson().toJson(response.body()))
                    }
                    try {
                        val jsonObject = JSONObject(response.errorBody()!!.string())
                        val message = jsonObject.getString(Constant.message)
                        when (jsonObject.getString(Constant.code)) {
                            Constant._400 -> {
                                listener.onFailedResponse(1, message)
                            }
                            Constant._401 -> {
                                Utils.logout(mContext, message)
                            }
                            else -> {
                                listener.onFailedResponse(
                                    2,
                                    mContext!!.getString(R.string.response_error)
                                )
                            }
                        }
                    } catch (e: JSONException) {
                        listener.onFailedResponse(3, mContext!!.getString(R.string.response_error))
                    } catch (e: IOException) {
                        listener.onFailedResponse(4, mContext!!.getString(R.string.response_error))
                    }
                }
            }

            override fun onFailure(call: Call<T>, t: Throwable) {
                if (Utils.isDebugging) {
                    Log.e("RESPONSE", "" + t.localizedMessage)
                }
                if (dialog.isShowing) {
                    dialog.dismiss()
                }
                //listener.onFailedResponse(0, t.localizedMessage!!)
                if (!call.isCanceled) {
                    listener.onFailedResponse(5, mContext!!.getString(R.string.response_error))
                }
            }
        })
    }

    interface ApiCompleteListener {
        fun <T> onSuccessResponse(jsonResponse: Response<T>)
        fun onFailedResponse(statusCode: Int, message: String)
    }
}


CustomDialog

package com.demo.restapi;
import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.view.Window;
import android.widget.ImageView;
import com.demo.R;
import com.bumptech.glide.Glide;

public class CustomDialog extends Dialog {

    private Context mContext;

    public CustomDialog(Context context) {
        super(context);
        mContext = context;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.dialog_loader);

        ImageView imgLoader = findViewById(R.id.img_loader);
        Glide.with(mContext).asGif().load(R.drawable.ripple_gif).into(imgLoader);
    }
}


package com.demo.pushnotification

import android.app.*
import android.content.Context
import android.content.Intent
import android.media.Ringtone
import android.media.RingtoneManager
import android.net.Uri
import android.os.Build
import android.util.Log
import androidx.core.app.NotificationCompat
import com.demo.R
import com.demo.global.Constant
import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.RemoteMessage
import com.demo.BuildConfig
import com.demo.activities.NotificationLogActivity
import com.demo.agent.AgentDashboardActivity
import com.demo.agent.AgentProfileActivity
import com.demo.doctor.*
import com.demo.global.Utils
import com.demo.patient.ChatActivity


class MyFirebaseMessagingService : FirebaseMessagingService() {

    override fun onMessageReceived(remoteMessage: RemoteMessage) {
        //Log.e("onMessageReceived", "" + remoteMessage)

        val isAuthentication = Utils.getData(this, Constant.is_authentication)
        /*if (isAuthentication == Constant.Y && remoteMessage.notification != null) {
             Log.e("notification", "" + remoteMessage.notification)
               val title = Utils.chkStr(remoteMessage.notification!!.title)
               val body = Utils.chkStr(remoteMessage.notification!!.body)
               val sound = Utils.chkStr(remoteMessage.notification!!.sound)
               val clickAction = Utils.chkStr(remoteMessage.notification!!.clickAction)
               val tag = Utils.chkStr(remoteMessage.notification!!.tag)
               //sendNotification(title, body, tag)
        }*/

        if (isAuthentication == Constant.Y && remoteMessage.data.isNotEmpty()) {
            //Log.e("data", "" + remoteMessage.data)
            val title = Utils.chkStr(remoteMessage.data[Constant.title])
            val text = Utils.chkStr(remoteMessage.data[Constant.text])
            val type = Utils.chkStr(remoteMessage.data[Constant.type])
            val id = Utils.chkStr(remoteMessage.data[Constant.id])
            sendNotification(title, text, type, id)
        }
    }

    private fun sendNotification(title: String, text: String, type: String, id: String) {
        val intent: Intent
        when (type) {
      
            "abc" -> {
                intent = Intent(this, ABCActivity::class.java)
                intent.putExtra(Constant.id, Utils.chkStr(id))
                intent.putExtra(Constant.appointment_status, Constant.create)
            }
            "xyz" -> {
                intent = Intent(this, XyzActivity::class.java)
                intent.putExtra(Constant.appointment_status, Constant.cancelled)
            } else -> {
                intent = Intent(this, NotificationLogActivity::class.java)
            }
        }
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
        val pendingIntent =
            PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)

        val notificationBuilder = NotificationCompat.Builder(this, BuildConfig.APPLICATION_ID)
            .setSmallIcon(R.drawable.ic_logo)
            .setContentTitle(Utils.htmlFormat(title))
            .setContentText(Utils.htmlFormat(text))
            .setStyle(NotificationCompat.BigTextStyle().bigText(Utils.htmlFormat(text)))
            .setDefaults(Notification.DEFAULT_ALL)
            .setContentIntent(pendingIntent)
            .setWhen(System.currentTimeMillis())
            .setAutoCancel(true)

        val notificationManager =
            getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager

        // Configure Notification Channel
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val channel = NotificationChannel(
                BuildConfig.APPLICATION_ID,
                resources.getString(R.string.app_name),
                NotificationManager.IMPORTANCE_DEFAULT
            )
            channel.enableLights(true)
            channel.enableVibration(true)
            channel.setSound(null, null)
            notificationManager.createNotificationChannel(channel)
            try {
                //val notification = Uri.parse("android.resource://" + packageName + "/" + R.raw.tone)
                val notification = Uri.parse("android.resource://$packageName/")
                val r: Ringtone = RingtoneManager.getRingtone(this, notification)
                r.play()
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
        notificationManager.notify(1, notificationBuilder.build())
    }


    override fun onNewToken(token: String) {
        if (Utils.isNotEmptyString(token)) {
            Utils.saveData(this, Constant.push_token, token.trim())
        }
    }
}

Marvel Api Integration In Android

                              Full Source Code Download Here: https://github.com/sanjaymangaroliya/MarvelApiIntegration.git MainA...