Vera 2.1 stable build

parent c1601154
Showing with 108 additions and 2141 deletions
......@@ -43,19 +43,6 @@
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustResize|stateHidden" />
<activity
android:name=".ui.OtpValidationActivity"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustResize|stateHidden" />
<activity
android:name=".ui.LoginChooseActivity"
android:screenOrientation="portrait"
/> <activity
android:name=".ui.ADALActivity"
android:screenOrientation="portrait"
/>
<activity android:name=".ui.ResetPasswordActivity"
android:screenOrientation="portrait"
android:fitsSystemWindows="true"
......

127 KB | W: | H:

13.9 KB | W: | H:

app/src/main/ic_launcher-web.png
app/src/main/ic_launcher-web.png
app/src/main/ic_launcher-web.png
app/src/main/ic_launcher-web.png
  • 2-up
  • Swipe
  • Onion skin
......@@ -40,10 +40,9 @@ import retrofit2.Retrofit;
public class IncidentApiManager {
public static void getIncident(Context context, GetIncidentApiListener listener) {
String sysId = PrefManager.getSharedPref(context, PrefManager.PREFERENCE_DYNAMIC_USER_SYS_ID);
CatalogueLog.d("IncidentApiManager: getIncident: ");
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("caller_id="+sysId);
stringBuilder.append("caller_id=javascript:gs.getUserID()");
CatalogueLog.d("IncidentApiManager: getIncident: request parameter: "+stringBuilder.toString());
String accessToken = PrefManager.getSharedPref(context, PrefManager.PREFERENCE_ACCESS_TOKEN);
......@@ -52,7 +51,6 @@ public class IncidentApiManager {
listener.onFailApiCall();
return;
}
final Retrofit retrofit = RestClient.getInitializedRestAdapter(accessToken);
Call<ResponseBody> call = retrofit.create(IncidentApi.class).getIncident(stringBuilder.toString(), "");
try {
......
......@@ -90,20 +90,20 @@ public class LoginApiManager {
})
.create();
LoginApiResponse loginApiResponse = gson.fromJson(jsonObject.toString(), LoginApiResponse.class);
listener.onDoneApiCall(loginApiResponse);
LoginApiResponse loginApiResponse = gson.fromJson(jsonObject.toString(), LoginApiResponse.class);
listener.onDoneApiCall(loginApiResponse);
} else
listener.onFailApiCall();
} catch (JSONException e) {
CatalogueLog.e("LoginApiManager: submitLoginValues: onResponse: ", e);
listener.onFailApiCall();
} catch (IOException e) {
CatalogueLog.e("LoginApiManager: submitLoginValues: onResponse: ", e);
listener.onFailApiCall();
}
} else {
CatalogueLog.e("LoginApiManager: submitLoginValues: onResponse: ", e);
listener.onFailApiCall();
} catch (IOException e) {
CatalogueLog.e("LoginApiManager: submitLoginValues: onResponse: ", e);
listener.onFailApiCall();
}
} else {
listener.onFailApiCall();
}
} catch (IOException e) {
CatalogueLog.e("LoginApiManager: submitLoginValues: IOException: ", e);
listener.onFailApiCall();
......
package com.vsoft.vera.ui;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.preference.PreferenceManager;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.android.volley.DefaultRetryPolicy;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonObjectRequest;
import com.android.volley.toolbox.Volley;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.target.SimpleTarget;
import com.bumptech.glide.request.transition.Transition;
import com.microsoft.aad.adal.ADALError;
import com.microsoft.aad.adal.AuthenticationCallback;
import com.microsoft.aad.adal.AuthenticationContext;
import com.microsoft.aad.adal.AuthenticationException;
import com.microsoft.aad.adal.AuthenticationResult;
import com.microsoft.aad.adal.IDispatcher;
import com.microsoft.aad.adal.Logger;
import com.microsoft.aad.adal.PromptBehavior;
import com.microsoft.aad.adal.Telemetry;
import com.vsoft.vera.CatalogueApplication;
import com.vsoft.vera.R;
import com.vsoft.vera.api.listeners.get.GetLiveAgentApiListener;
import com.vsoft.vera.api.listeners.get.GetUserDetailApiListener;
import com.vsoft.vera.api.listeners.get.GetUserLoginApiListener;
import com.vsoft.vera.api.listeners.put.PutDeviceRegistrationApiListener;
import com.vsoft.vera.api.managers.LoginApiManager;
import com.vsoft.vera.api.managers.UserApiManager;
import com.vsoft.vera.api.pojos.ChatHistoryPostData;
import com.vsoft.vera.api.pojos.LoginApiResponse;
import com.vsoft.vera.db.managers.ChatBotHistoryManager;
import com.vsoft.vera.db.managers.ChatBotUserManager;
import com.vsoft.vera.db.models.ChatBotUser;
import com.vsoft.vera.db.models.UserApiValues;
import com.vsoft.vera.enums.SyncStatus;
import com.vsoft.vera.utils.Constants;
import com.vsoft.vera.utils.DialogUtils;
import com.vsoft.vera.utils.GenerateRandomString;
import com.vsoft.vera.utils.NetworkConnectivity;
import com.vsoft.vera.utils.PrefManager;
import com.vsoft.vera.utils.Util;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import static com.vsoft.vera.utils.Util.convertDpToPx;
public class ADALActivity extends AppCompatActivity {
/* UI & Debugging Variables */
private static final String TAG = ADALActivity.class.getSimpleName();
Button callGraphButton;
Button signOutButton;
Button login_with_otp;
ImageView logo_banner;
private static final int API_SUCCESS_USER_LOGIN = 1;
private static final int API_FAIL_USER_LOGIN = 2;
private static final int API_SUCCESS_USER_DETAIL = 3;
private static final int API_FAIL_USER_DETAIL = 4;
private List<UserApiValues> mUserDetails;
private ProgressDialog mProgressDlg;
/* Azure AD Constants */
/* Authority is in the form of https://login.microsoftonline.com/yourtenant.onmicrosoft.com */
private static final String AUTHORITY = "https://login.microsoftonline.com/common";
/* The clientID of your application is a unique identifier which can be obtained from the app registration portal */
private static final String CLIENT_ID = "b9808fea-11a7-4ed5-aab0-baae8688adb4";
/* Resource URI of the endpoint which will be accessed */
private static final String RESOURCE_ID = "https://graph.microsoft.com/";
/* The Redirect URI of the application (Optional) */
private static final String REDIRECT_URI = "x-msauth-com.com.vsoft.vmetrics://com.vsoft.vmetrics";
/* Microsoft Graph Constants */
private final static String MSGRAPH_URL = "https://graph.microsoft.com/v1.0/me";
/* Azure AD Variables */
private AuthenticationContext mAuthContext;
private AuthenticationResult mAuthResult;
/* Handler to do an interactive sign in and acquire token */
private Handler mAcquireTokenHandler;
/* Boolean variable to ensure invocation of interactive sign-in only once in case of multiple acquireTokenSilent call failures */
private static AtomicBoolean sIntSignInInvoked = new AtomicBoolean();
/* Constant to send message to the mAcquireTokenHandler to do acquire token with Prompt.Auto*/
private static final int MSG_INTERACTIVE_SIGN_IN_PROMPT_AUTO = 1;
/* Constant to send message to the mAcquireTokenHandler to do acquire token with Prompt.Always */
private static final int MSG_INTERACTIVE_SIGN_IN_PROMPT_ALWAYS = 2;
/* Constant to store user id in shared preferences */
private static final String USER_ID = "user_id";
private boolean isLogin= false;
private boolean sspLogin= false;
/* Telemetry variables */
// Flag to turn event aggregation on/off
private static final boolean sTelemetryAggregationIsRequired = true;
private LinearLayout mainLayt;
private Handler mWaitHandler = new Handler();
/* Telemetry dispatcher registration */
static {
Telemetry.getInstance().registerDispatcher(new IDispatcher() {
@Override
public void dispatchEvent(Map<String, String> events) {
// Events from ADAL will be sent to this callback
for(Map.Entry<String, String> entry: events.entrySet()) {
Log.d(TAG, entry.getKey() + ": " + entry.getValue());
}
}
}, sTelemetryAggregationIsRequired);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.adal_main);
mainLayt = (LinearLayout) findViewById(R.id.activity_main);
logo_banner = findViewById(R.id.logo_banner);
Glide.with(this).load(R.drawable.fulton_bg).into(new SimpleTarget<Drawable>() {
@Override
public void onResourceReady(Drawable resource, Transition<? super Drawable> transition) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
mainLayt.setBackground(resource);
}
}
});
Glide.with(this).load(R.drawable.fulton_county_logo_home).into(new SimpleTarget<Drawable>() {
@Override
public void onResourceReady(Drawable resource, Transition<? super Drawable> transition) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
logo_banner.setBackground(resource);
}
}
});
// CheckLoginValues();
callGraphButton = (Button) findViewById(R.id.callGraph);
signOutButton = (Button) findViewById(R.id.clearCache);
login_with_otp = (Button) findViewById(R.id.login_with_otp);
callGraphButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if (NetworkConnectivity.haveNetworkConnection(ADALActivity.this)) {
onCallGraphClicked();
} else {
DialogUtils.showNoConnectionDialog(ADALActivity .this);
}
}
});
login_with_otp.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// onSignOutClicked();
Intent intent = new Intent(ADALActivity.this,OtpValidationActivity.class);
startActivity(intent);
}
});
mAuthContext = new AuthenticationContext(getApplicationContext(), AUTHORITY, false);
/* Instantiate handler which can invoke interactive sign-in to get the Resource
* sIntSignInInvoked ensures interactive sign-in is invoked one at a time */
mAcquireTokenHandler = new Handler(Looper.getMainLooper()){
@Override
public void handleMessage(Message msg) {
if( sIntSignInInvoked.compareAndSet(false, true)) {
if (msg.what == MSG_INTERACTIVE_SIGN_IN_PROMPT_AUTO){
mAuthContext.acquireToken(getActivity(), RESOURCE_ID, CLIENT_ID, REDIRECT_URI, PromptBehavior.Always, getAuthInteractiveCallback());
} else if(msg.what == MSG_INTERACTIVE_SIGN_IN_PROMPT_ALWAYS){
mAuthContext.acquireToken(getActivity(), RESOURCE_ID, CLIENT_ID, REDIRECT_URI, PromptBehavior.Always, getAuthInteractiveCallback());
}
}
}
};
/* ADAL Logging callback setup */
Logger.getInstance().setExternalLogger(new Logger.ILogger() {
@Override
public void Log(String tag, String message, String additionalMessage, Logger.LogLevel level, ADALError errorCode) {
// You can filter the logs depending on level or errorcode.
Log.d(TAG, message + " " + additionalMessage);
}
});
/*Attempt an acquireTokenSilent call to see if we're signed in*/
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
String userId = preferences.getString(USER_ID, "");
if(!TextUtils.isEmpty(userId)){
mAuthContext.acquireTokenSilentAsync(RESOURCE_ID, CLIENT_ID, userId, getAuthSilentCallback());
}else {
mAuthContext.getCache().removeAll();
}
}
private void CheckLoginValues() {
String sysId = PrefManager.getSharedPref(ADALActivity.this, PrefManager.PREFERENCE_USER_SYS_ID);
if (!TextUtils.isEmpty(sysId)) {
/*Send broadcast to start SyncService*/
Intent intent = new Intent(Constants.APPLICATION_BROADCAST_INTENT);
intent.putExtra(Constants.APPLICATION_BROADCAST_DATA_ACTION, Constants.ACTION_SYNC);
LocalBroadcastManager.getInstance(ADALActivity.this).sendBroadcast(intent);
Bundle bundle = getIntent().getExtras();
if(bundle != null) {
int requestCode = bundle.getInt(Constants.DATA_KEY_LOGIN_REQUEST_CODE);
if (requestCode == Constants.LOGIN_SCREEN_REQUEST_CODE) {
setResult(Constants.LOGIN_SCREEN_REQUEST_CODE, new Intent());
} else {
Intent homeIntent = new Intent(ADALActivity.this, HomeScreen.class);
homeIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(homeIntent);
}
} else {
Intent homeIntent = new Intent(ADALActivity.this, HomeScreen.class);
homeIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(homeIntent);
}
isLogin = true;
finish();
}
}
//
// Core Auth methods used by ADAL
// ==================================
// onActivityResult() - handles redirect from System browser
// onCallGraphClicked() - attempts to get tokens for graph, if it succeeds calls graph & updates UI
// callGraphAPI() - called on successful token acquisition which makes an HTTP request to graph
// onSignOutClicked() - Signs user out of the app & updates UI
//
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(resultCode == 2003){
/* update the UI to post call graph state */
runOnUiThread(new Runnable() {
@Override
public void run() {
updateSuccessUI();
}
});
}
mAuthContext.onActivityResult(requestCode, resultCode, data);
}
/*
* End user clicked call Graph API button, time for Auth
* Use ADAL to get an Access token for the Microsoft Graph API
*/
private void onCallGraphClicked() {
mAcquireTokenHandler.sendEmptyMessage(MSG_INTERACTIVE_SIGN_IN_PROMPT_AUTO);
}
private void callGraphAPI() {
Log.d(TAG, "Starting volley request to graph");
mProgressDlg = new ProgressDialog(ADALActivity.this);
mProgressDlg.setMessage(getString(R.string.loading_string));
mProgressDlg.show();
mProgressDlg.setCancelable(false);
/* Make sure we have a token to send to graph */
if (mAuthResult.getAccessToken() == null) {return;}
RequestQueue queue = Volley.newRequestQueue(this);
JSONObject parameters = new JSONObject();
try {
parameters.put("key", "value");
} catch (Exception e) {
Log.d(TAG, "Failed to put parameters: " + e.toString());
}
final JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, MSGRAPH_URL,
parameters,new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
mProgressDlg.dismiss();
/* Successfully called graph, process data and send to UI */
Log.d(TAG, "Response: " + response.toString());
JSONObject root = null;
try {
root = new JSONObject(response.toString());
String userLoginName = root.getString("givenName");
/*Send broadcast to start SyncService*/
String mail = root.getString("mail");
PrefManager.setSharedPref(ADALActivity.this, PrefManager.PREFERENCE_USER_FULL_NAME, userLoginName);
PrefManager.setSharedPref(ADALActivity.this, PrefManager.PREFERENCE_USER_EMAIL_ID, mail);
if(!isLogin){
new LoginDetailsSendToServer().execute();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
mProgressDlg.dismiss();
Log.d(TAG, "Error: " + error.toString());
}
}) {
@Override
public Map<String, String> getHeaders() {
Map<String, String> headers = new HashMap<>();
headers.put("Authorization", "Bearer " + mAuthResult.getAccessToken());
return headers;
}
};
Log.d(TAG, "Adding HTTP GET to Queue, Request: " + request.toString());
request.setRetryPolicy(new DefaultRetryPolicy(
3000,
DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
queue.add(request);
}
private void onSignOutClicked() {
// End user has clicked the Sign Out button
// Kill the token cache
// Optionally call the signout endpoint to fully sign out the user account
mAuthContext.getCache().removeAll();
// updateSignedOutUI();
}
//
// UI Helper methods
// ================================
// updateGraphUI() - Sets graph response in UI
// updateSuccessUI() - Updates UI when token acquisition succeeds
// updateSignedOutUI() - Updates UI when app sign out succeeds
//
private void updateGraphUI(JSONObject response) {
// Called on success from /me endpoint
// Writes graph data to the UI
TextView graphText = (TextView) findViewById(R.id.graphData);
graphText.setText(response.toString());
}
@SuppressLint("SetTextI18n")
private void updateSuccessUI() {
// Called on success from /me endpoint
// Removed call Graph API button and paint Sign out
callGraphButton.setVisibility(View.GONE);
login_with_otp.setVisibility(View.GONE);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(convertDpToPx(this, 300),
convertDpToPx(this, 450));
layoutParams.setMargins(convertDpToPx(this, 55), convertDpToPx(this, 30), convertDpToPx(this, 30), convertDpToPx(this, 30));
logo_banner.setLayoutParams(layoutParams);
signOutButton.setVisibility(View.GONE);
findViewById(R.id.welcome).setVisibility(View.GONE);
/*((TextView) findViewById(R.id.welcome)).setText("Welcome, " +
mAuthResult.getUserInfo().getGivenName());*/
findViewById(R.id.graphData).setVisibility(View.GONE);
}
@SuppressLint("SetTextI18n")
private void updateSignedOutUI() {
signOutButton.setVisibility(View.GONE);
findViewById(R.id.welcome).setVisibility(View.INVISIBLE);
findViewById(R.id.graphData).setVisibility(View.INVISIBLE);
((TextView) findViewById(R.id.graphData)).setText("No Data");
}
//
// ADAL Callbacks
// ======================
// getActivity() - returns activity so we can acquireToken within a callback
// getAuthSilentCallback() - callback defined to handle acquireTokenSilent() case
// getAuthInteractiveCallback() - callback defined to handle acquireToken() case
//
public Activity getActivity() {
return this;
}
/* Callback used in for silent acquireToken calls.
* Looks if tokens are in the cache (refreshes if necessary and if we don't forceRefresh)
* else errors that we need to do an interactive request.
*/
private AuthenticationCallback<AuthenticationResult> getAuthSilentCallback() {
return new AuthenticationCallback<AuthenticationResult>() {
@Override
public void onSuccess(AuthenticationResult authenticationResult) {
if(authenticationResult==null || TextUtils.isEmpty(authenticationResult.getAccessToken())
|| authenticationResult.getStatus()!= AuthenticationResult.AuthenticationStatus.Succeeded){
Log.d(TAG, "Silent acquire token Authentication Result is invalid, retrying with interactive");
/* retry with interactive */
mAcquireTokenHandler.sendEmptyMessage(MSG_INTERACTIVE_SIGN_IN_PROMPT_AUTO);
return;
}
/* Successfully got a token, call graph now */
Log.d(TAG, "Successfully authenticated");
/* Store the mAuthResult */
mAuthResult = authenticationResult;
/* call graph */
callGraphAPI();
/* update the UI to post call graph state */
/*runOnUiThread(new Runnable() {
@Override
public void run() {
updateSuccessUI();
}
});*/
}
@Override
public void onError(Exception exception) {
/* Failed to acquireToken */
Log.e(TAG, "Authentication failed: " + exception.toString());
if (exception instanceof AuthenticationException) {
AuthenticationException authException = ((AuthenticationException) exception);
ADALError error = authException.getCode();
logHttpErrors(authException);
/* Tokens expired or no session, retry with interactive */
if (error == ADALError.AUTH_REFRESH_FAILED_PROMPT_NOT_ALLOWED ) {
mAcquireTokenHandler.sendEmptyMessage(MSG_INTERACTIVE_SIGN_IN_PROMPT_AUTO);
}else if(error == ADALError.NO_NETWORK_CONNECTION_POWER_OPTIMIZATION){
/* Device is in Doze mode or App is in stand by mode.
Wake up the app or show an appropriate prompt for the user to take action
More information on this : https://github.com/AzureAD/azure-activedirectory-library-for-android/wiki/Handle-Doze-and-App-Standby */
Log.e(TAG, "Device is in doze mode or the app is in standby mode");
}
return;
}
/* Attempt an interactive on any other exception */
mAcquireTokenHandler.sendEmptyMessage(MSG_INTERACTIVE_SIGN_IN_PROMPT_AUTO);
}
};
}
private void logHttpErrors(AuthenticationException authException){
int httpResponseCode = authException.getServiceStatusCode();
Log.d(TAG , "HTTP Response code: " + authException.getServiceStatusCode());
if(httpResponseCode< 200 || httpResponseCode >300) {
// logging http response headers in case of a http error.
HashMap<String, List<String>> headers = authException.getHttpResponseHeaders();
if (headers != null) {
StringBuilder sb = new StringBuilder();
for (Map.Entry<String, List<String>> entry : headers.entrySet()) {
sb.append(entry.getKey());
sb.append(":");
sb.append(entry.getValue().toString());
sb.append("; ");
}
Log.e(TAG, "HTTP Response headers: " + sb.toString());
}
}
}
/* Callback used for interactive request. If succeeds we use the access
* token to call the Microsoft Graph. Does not check cache
*/
private AuthenticationCallback<AuthenticationResult> getAuthInteractiveCallback() {
return new AuthenticationCallback<AuthenticationResult>() {
@Override
public void onSuccess(AuthenticationResult authenticationResult) {
if(authenticationResult==null || TextUtils.isEmpty(authenticationResult.getAccessToken())
|| authenticationResult.getStatus()!= AuthenticationResult.AuthenticationStatus.Succeeded){
Log.e(TAG, "Authentication Result is invalid");
return;
}
/* Successfully got a token, call graph now */
Log.d(TAG, "Successfully authenticated");
Log.d(TAG, "ID Token: " + authenticationResult.getIdToken());
/* Store the auth result */
mAuthResult = authenticationResult;
/* Store User id to SharedPreferences to use it to acquire token silently later */
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
preferences.edit().putString(USER_ID, authenticationResult.getUserInfo().getUserId()).apply();
/* call graph */
callGraphAPI();
/* update the UI to post call graph state */
/*runOnUiThread(new Runnable() {
@Override
public void run() {
updateSuccessUI();
}
});*/
/* set the sIntSignInInvoked boolean back to false */
sIntSignInInvoked.set(false);
}
@Override
public void onError(Exception exception) {
/* Failed to acquireToken */
Log.e(TAG, "Authentication failed: " + exception.toString());
if (exception instanceof AuthenticationException) {
ADALError error = ((AuthenticationException)exception).getCode();
if(error==ADALError.AUTH_FAILED_CANCELLED){
Log.e(TAG, "The user cancelled the authorization request");
}else if(error== ADALError.AUTH_FAILED_NO_TOKEN){
// In this case ADAL has found a token in cache but failed to retrieve it.
// Retry interactive with Prompt.Always to ensure we do an interactive sign in
mAcquireTokenHandler.sendEmptyMessage(MSG_INTERACTIVE_SIGN_IN_PROMPT_ALWAYS);
}else if(error == ADALError.NO_NETWORK_CONNECTION_POWER_OPTIMIZATION){
/* Device is in Doze mode or App is in stand by mode.
Wake up the app or show an appropriate prompt for the user to take action
More information on this : https://github.com/AzureAD/azure-activedirectory-library-for-android/wiki/Handle-Doze-and-App-Standby */
Log.e(TAG, "Device is in doze mode or the app is in standby mode");
}
}
/* set the sIntSignInInvoked boolean back to false */
sIntSignInInvoked.set(false);
}
};
}
private class LoginDetailsSendToServer extends AsyncTask<Void, Integer, Integer> {
private ProgressDialog progressDialog;
private static final int USER_DETAIL = 1;
private int apiStatus;
@Override
protected void onPreExecute() {
super.onPreExecute();
progressDialog = new ProgressDialog(ADALActivity.this);
progressDialog.setMessage(getString(R.string.loading_string));
progressDialog.show();
progressDialog.setCancelable(false);
}
@Override
protected Integer doInBackground(Void... params) {
LoginApiManager.submitLoginValues(LoginApiResponse.Json.PASSWORD, Constants.LOGIN_CLIENT_ID, Constants
.LOGIN_CLIENT_SECRET, Constants.FULTON_LOGIN_USERNAME,Constants.FULTON_LOGIN_PASSWORD, new GetUserLoginApiListener() {
@Override
public void onDoneApiCall(LoginApiResponse loginApiResponse) {
apiStatus = API_SUCCESS_USER_LOGIN;
publishProgress(USER_DETAIL);
/*Save access token in Preference*/
PrefManager.setSharedPref(ADALActivity.this, PrefManager.PREFERENCE_ACCESS_TOKEN, loginApiResponse.getAccessToken());
PrefManager.setSharedPref(ADALActivity.this, PrefManager.PREFERENCE_REFRESH_TOKEN, loginApiResponse.getRefreshToken());
UserApiManager.getUserDetailResponse(ADALActivity.this, Constants.FULTON_LOGIN_USERNAME, new GetUserDetailApiListener() {
@Override
public void onDoneApiCall(List<UserApiValues> userValues) {
mUserDetails = userValues;
if(Util.isNotificationsItemEnabled()) {
UserApiManager.putDeviceRegistration(ADALActivity.this, userValues.get(0).getSysId(), new PutDeviceRegistrationApiListener() {
@Override
public void onDoneApiCall() {
apiStatus = API_SUCCESS_USER_DETAIL;
}
@Override
public void onFailApiCall() {
apiStatus = API_FAIL_USER_DETAIL;
}
});
} else {
apiStatus = API_SUCCESS_USER_DETAIL;
}
}
@Override
public void onFailApiCall() {
apiStatus = API_FAIL_USER_DETAIL;
}
});
}
@Override
public void onFailApiCall() {
apiStatus = API_FAIL_USER_LOGIN;
}
});
return apiStatus;
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
if(values[0] == USER_DETAIL) {
// progressDialog.setMessage(getString(R.string.login_screen_getting_user_detail_loading_string));
}
}
@Override
protected void onPostExecute(Integer syncStatus) {
super.onPostExecute(syncStatus);
if (progressDialog != null && progressDialog.isShowing()) {
progressDialog.dismiss();
}
if (syncStatus == API_SUCCESS_USER_DETAIL) {
if (mUserDetails != null) {
isLogin = true;
if (((CatalogueApplication) getApplication()).isNetConnected()) {
ChatBotHistoryManager.delete();
String generateRandomStrPharma = GenerateRandomString.randomString(30);
PrefManager.setSharedPref(ADALActivity.this, PrefManager.SESSION_ID, generateRandomStrPharma);
} else {
DialogUtils.showNoConnectionDialog(ADALActivity.this);
}
String generateRandoStrPharma = GenerateRandomString.randomString(30);
PrefManager.setSharedPref(ADALActivity.this, PrefManager.SESSION_ID, generateRandoStrPharma);
String firstName = mUserDetails.get(0).getFirstName();
String lastName = mUserDetails.get(0).getLastName();
String sysid = mUserDetails.get(0).getSysId();
String userFullName = mUserDetails.get(0).getFullName();
String userId = mUserDetails.get(0).getUserId();
String userEmailId = mUserDetails.get(0).getUserEmailId();
if(Util.isChatItemEnabled()) {
/*Start Chat Local DB Part*/
//Here we'll save logged in user detail in local DB for chat history.
ChatBotUser localChatBotUser = ChatBotUserManager.getChatBotUsersByUserSysId(sysid);
if (localChatBotUser == null) {
/*Clears all data from CHAT_BOT_HISTORY and CHAT_BOT_USER tables*/
ChatBotHistoryManager.deleteAllRows();
ChatBotUserManager.deleteAllRows();
/*Save Logged in user in local db for chat screen*/
ChatBotUser chatBotUser = ChatBotUser.ChatBotUserBuilder.aChatBotUser()
.setUserSysId(sysid)
.setName(firstName)
.build();
ChatBotUserManager.save(chatBotUser);
} else {//Update the name of user
localChatBotUser.setName(firstName);
ChatBotUserManager.update(localChatBotUser);
}
}
/*End Chat Local DB Part*/
PrefManager.setSharedPref(ADALActivity.this, PrefManager.PREFERENCE_USER_FIRST_NAME, firstName);
PrefManager.setSharedPref(ADALActivity.this, PrefManager.PREFERENCE_USER_LAST_NAME, lastName);
PrefManager.setSharedPref(ADALActivity.this, PrefManager.PREFERENCE_USER_SYS_ID, sysid);
/*For pre fill value in variable form*/
PrefManager.setSharedPref(ADALActivity.this, PrefManager.PREFERENCE_USER_ID, userId);
new GetyUserSysIDAsync().execute();
//
} else {
Util.simpleAlert(ADALActivity.this,getResources().getString(R.string.user_detail_not_available));
}
} else if (syncStatus == API_FAIL_USER_LOGIN) {
Util.simpleAlert(ADALActivity.this,getResources().getString(R.string.login_screen_invalid_username_and_password_string));
} else if (syncStatus == API_FAIL_USER_DETAIL) {
Util.simpleAlert(ADALActivity.this,getResources().getString(R.string.failed_to_fetch_user_detail_string));
}
}
}
private class GetyUserSysIDAsync extends AsyncTask<Void, Void, SyncStatus> {
private ProgressDialog progressDialog;
private SyncStatus syncStatus = SyncStatus.FAIL;
String userSysId;
String accessToken;
String email,userFullName;
@Override
protected void onPreExecute() {
super.onPreExecute();
progressDialog = new ProgressDialog(ADALActivity.this);
progressDialog.setMessage(getString(R.string.login_screen_logging_in_loading_string));
progressDialog.show();
progressDialog.setCancelable(false);
accessToken = PrefManager.getSharedPref(ADALActivity.this, PrefManager.PREFERENCE_ACCESS_TOKEN);
email = PrefManager.getSharedPref(ADALActivity.this, PrefManager.PREFERENCE_USER_EMAIL_ID);
userFullName = PrefManager.getSharedPref(ADALActivity.this, PrefManager.PREFERENCE_USER_FULL_NAME);
}
@Override
protected SyncStatus doInBackground(Void... params) {
UserApiManager.getUserSysId(ADALActivity.this,accessToken,email,new GetLiveAgentApiListener() {
@Override
public void onDoneApiCall(String url) {
userSysId = url;
PrefManager.setSharedPref(ADALActivity.this, PrefManager.PREFERENCE_DYNAMIC_USER_SYS_ID, userSysId);
syncStatus = SyncStatus.SUCCESS;
}
@Override
public void onFailApiCall() {
syncStatus = SyncStatus.FAIL;
}
});
return syncStatus;
}
@Override
protected void onPostExecute(SyncStatus syncStatus) {
super.onPostExecute(syncStatus);
if (progressDialog != null && progressDialog.isShowing()) {
progressDialog.dismiss();
}
if (syncStatus == SyncStatus.SUCCESS) {
if(userSysId != null){
/*Send broadcast to start SyncService*/
Intent intent = new Intent(Constants.APPLICATION_BROADCAST_INTENT);
intent.putExtra(Constants.APPLICATION_BROADCAST_DATA_ACTION, Constants.ACTION_SYNC);
LocalBroadcastManager.getInstance(ADALActivity.this).sendBroadcast(intent);
Bundle bundle = getIntent().getExtras();
if(bundle != null) {
int requestCode = bundle.getInt(Constants.DATA_KEY_LOGIN_REQUEST_CODE);
if (requestCode == Constants.LOGIN_SCREEN_REQUEST_CODE) {
startActivity(new Intent(ADALActivity.this, ChatActivity.class));
} else {
Intent homeIntent = new Intent(ADALActivity.this, HomeScreen.class);
homeIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(homeIntent);
}
} else {
Intent homeIntent = new Intent(ADALActivity.this, HomeScreen.class);
homeIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(homeIntent);
}
}else {
Util.simpleAlert(ADALActivity.this,getResources().getString(R.string.user_detail_not_available));
}
} else if (syncStatus == SyncStatus.FAIL) {
Util.simpleAlert(ADALActivity.this,getResources().getString(R.string.failed_to_fetch_user_detail_string));
}
}
}
}
......@@ -207,11 +207,11 @@ public class ChatActivity extends AppCompatActivity implements OnDSListener, OnD
mLoggedInUserSysId = PrefManager.getSharedPref(this, PrefManager.PREFERENCE_USER_SYS_ID);
mLoggedInUsername = PrefManager.getSharedPref(this, PrefManager.PREFERENCE_USER_FIRST_NAME);
userSysId = PrefManager.getSharedPref(this, PrefManager.PREFERENCE_DYNAMIC_USER_SYS_ID);
userSysId = PrefManager.getSharedPref(this, PrefManager.PREFERENCE_USER_SYS_ID);
if(TextUtils.isEmpty(mLoggedInUserSysId) || TextUtils.isEmpty(mLoggedInUsername)) {
CatalogueLog.e("User Sys id or Name is Null");
Intent intent = new Intent(this, ADALActivity.class);
Intent intent = new Intent(this, LoginScreen.class);
intent.putExtra(Constants.DATA_KEY_LOGIN_REQUEST_CODE, Constants.LOGIN_SCREEN_REQUEST_CODE);
startActivity(intent);
finish();
......
......@@ -172,80 +172,36 @@ public class HomeScreen extends HandleNotificationActivity {
// alert.show();
// }
// if(BuildConfig.BUILD_TYPE_INT == 1 ||BuildConfig.BUILD_TYPE_INT == 3 ) {
// AlertDialog.Builder builder = new AlertDialog.Builder(this);
// StringBuilder stringBuilder = new StringBuilder();
// stringBuilder.append("ServiceNow Instance: ");
// stringBuilder.append(Constants.DOMAIN);
// stringBuilder.append("\n");
// stringBuilder.append("Socket URL: ");
// stringBuilder.append(Constants.CHAT_SERVER_URL);
// stringBuilder.append("\n");
// stringBuilder.append("Flavor: ");
// stringBuilder.append(BuildConfig.FLAVOR);
// stringBuilder.append("\n");
// stringBuilder.append("Build Type: ");
// stringBuilder.append(BuildConfig.BUILD_TYPE);
// stringBuilder.append("\n");
// stringBuilder.append("\n");
// stringBuilder.append("Version: "+BuildConfig.VERSION_NAME);
// builder.setMessage(stringBuilder.toString())
// .setTitle("App Info")
// .setCancelable(false)
// .setPositiveButton(R.string.ok_string, new DialogInterface.OnClickListener() {
// public void onClick(DialogInterface dialog, int id) {
// dialog.dismiss();
// }
// });
// AlertDialog alert = builder.create();
// alert.show();
// }
if(BuildConfig.BUILD_TYPE_INT == 1 ||BuildConfig.BUILD_TYPE_INT == 3 ) {
String userFullName = PrefManager.getSharedPref(HomeScreen.this, PrefManager.PREFERENCE_USER_FULL_NAME);
if(userFullName!= null){
AlertDialog.Builder builder = new AlertDialog.Builder(this);
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("Username: ");
stringBuilder.append(userFullName);
stringBuilder.append("\n");
stringBuilder.append("\n");
stringBuilder.append("Version: "+BuildConfig.VERSION_NAME);
builder.setMessage(stringBuilder.toString())
.setTitle("User Details")
.setCancelable(false)
.setPositiveButton(R.string.ok_string, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.dismiss();
}
});
AlertDialog alert = builder.create();
alert.show();
}else {
String mobileNumber = PrefManager.getSharedPref(HomeScreen.this, PrefManager.MOBILE_NUMBER);
AlertDialog.Builder builder = new AlertDialog.Builder(this);
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("Username: ");
stringBuilder.append(mobileNumber);
stringBuilder.append("\n");
stringBuilder.append("\n");
stringBuilder.append("Version: "+BuildConfig.VERSION_NAME);
builder.setMessage(stringBuilder.toString())
.setTitle("User Details")
.setCancelable(false)
.setPositiveButton(R.string.ok_string, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.dismiss();
}
});
AlertDialog alert = builder.create();
alert.show();
}
if(BuildConfig.BUILD_TYPE_INT == 1 ||BuildConfig.BUILD_TYPE_INT == 3 ) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("ServiceNow Instance: ");
stringBuilder.append(Constants.DOMAIN);
stringBuilder.append("\n");
stringBuilder.append("Socket URL: ");
stringBuilder.append(Constants.CHAT_SERVER_URL);
stringBuilder.append("\n");
stringBuilder.append("Flavor: ");
stringBuilder.append(BuildConfig.FLAVOR);
stringBuilder.append("\n");
stringBuilder.append("Build Type: ");
stringBuilder.append(BuildConfig.BUILD_TYPE);
stringBuilder.append("\n");
stringBuilder.append("\n");
stringBuilder.append("Version: "+BuildConfig.VERSION_NAME);
builder.setMessage(stringBuilder.toString())
.setTitle("App Info")
.setCancelable(false)
.setPositiveButton(R.string.ok_string, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.dismiss();
}
});
AlertDialog alert = builder.create();
alert.show();
}
}
@OnClick(R.id.home_screen_logout_image_view)
......@@ -350,10 +306,8 @@ public class HomeScreen extends HandleNotificationActivity {
PrefManager.setSharedPref(HomeScreen.this, PrefManager.PREFERENCE_USER_FULL_NAME, "");
PrefManager.setSharedPref(HomeScreen.this, PrefManager.PREFERENCE_USER_EMAIL_ID, "");
PrefManager.setSharedPref(HomeScreen.this, PrefManager.SESSION_ID, "");
PrefManager.setSharedPref(HomeScreen.this, PrefManager.MOBILE_NUMBER, "");
PrefManager.setSharedPref(HomeScreen.this, PrefManager.PREFERENCE_DYNAMIC_USER_SYS_ID, "");
Intent loginIntent = new Intent(HomeScreen.this, ADALActivity.class);
Intent loginIntent = new Intent(HomeScreen.this, LoginScreen.class);
loginIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(loginIntent);
} else {
......
package com.vsoft.vera.ui;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.preference.PreferenceManager;
import android.support.v4.content.LocalBroadcastManager;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.android.volley.DefaultRetryPolicy;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonObjectRequest;
import com.android.volley.toolbox.Volley;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.target.SimpleTarget;
import com.bumptech.glide.request.transition.Transition;
import com.microsoft.aad.adal.ADALError;
import com.microsoft.aad.adal.AuthenticationCallback;
import com.microsoft.aad.adal.AuthenticationContext;
import com.microsoft.aad.adal.AuthenticationException;
import com.microsoft.aad.adal.AuthenticationResult;
import com.microsoft.aad.adal.IDispatcher;
import com.microsoft.aad.adal.Logger;
import com.microsoft.aad.adal.PromptBehavior;
import com.microsoft.aad.adal.Telemetry;
import com.vsoft.vera.CatalogueApplication;
import com.vsoft.vera.R;
import com.vsoft.vera.api.listeners.get.GetUserDetailApiListener;
import com.vsoft.vera.api.listeners.get.GetUserLoginApiListener;
import com.vsoft.vera.api.listeners.put.PutDeviceRegistrationApiListener;
import com.vsoft.vera.api.managers.LoginApiManager;
import com.vsoft.vera.api.managers.UserApiManager;
import com.vsoft.vera.api.pojos.LoginApiResponse;
import com.vsoft.vera.db.managers.ChatBotHistoryManager;
import com.vsoft.vera.db.managers.ChatBotUserManager;
import com.vsoft.vera.db.models.ChatBotUser;
import com.vsoft.vera.db.models.UserApiValues;
import com.vsoft.vera.utils.Constants;
import com.vsoft.vera.utils.DialogUtils;
import com.vsoft.vera.utils.GenerateRandomString;
import com.vsoft.vera.utils.NetworkConnectivity;
import com.vsoft.vera.utils.PrefManager;
import com.vsoft.vera.utils.Util;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
public class LoginChooseActivity extends Activity {
/* UI & Debugging Variables */
private static final String TAG = ADALActivity.class.getSimpleName();
private static final int API_SUCCESS_USER_LOGIN = 1;
private static final int API_FAIL_USER_LOGIN = 2;
private static final int API_SUCCESS_USER_DETAIL = 3;
private static final int API_FAIL_USER_DETAIL = 4;
private List<UserApiValues> mUserDetails;
private ProgressDialog mProgressDlg;
/* Azure AD Constants */
/* Authority is in the form of https://login.microsoftonline.com/yourtenant.onmicrosoft.com */
private static final String AUTHORITY = "https://login.microsoftonline.com/common";
/* The clientID of your application is a unique identifier which can be obtained from the app registration portal */
private static final String CLIENT_ID = "b9808fea-11a7-4ed5-aab0-baae8688adb4";
/* Resource URI of the endpoint which will be accessed */
private static final String RESOURCE_ID = "https://graph.microsoft.com/";
/* The Redirect URI of the application (Optional) */
private static final String REDIRECT_URI = "x-msauth-com.com.vsoft.vmetrics://com.vsoft.vmetrics";
/* Microsoft Graph Constants */
private final static String MSGRAPH_URL = "https://graph.microsoft.com/v1.0/me";
/* Azure AD Variables */
private AuthenticationContext mAuthContext;
private AuthenticationResult mAuthResult;
/* Handler to do an interactive sign in and acquire token */
private Handler mAcquireTokenHandler;
/* Boolean variable to ensure invocation of interactive sign-in only once in case of multiple acquireTokenSilent call failures */
private static AtomicBoolean sIntSignInInvoked = new AtomicBoolean();
/* Constant to send message to the mAcquireTokenHandler to do acquire token with Prompt.Auto*/
private static final int MSG_INTERACTIVE_SIGN_IN_PROMPT_AUTO = 1;
/* Constant to send message to the mAcquireTokenHandler to do acquire token with Prompt.Always */
private static final int MSG_INTERACTIVE_SIGN_IN_PROMPT_ALWAYS = 2;
/* Constant to store user id in shared preferences */
private static final String USER_ID = "user_id";
private boolean isLogin= false;
private boolean sspLogin= false;
/* Telemetry variables */
// Flag to turn event aggregation on/off
private static final boolean sTelemetryAggregationIsRequired = true;
private LinearLayout mainLayt;
/* Telemetry dispatcher registration */
static {
Telemetry.getInstance().registerDispatcher(new IDispatcher() {
@Override
public void dispatchEvent(Map<String, String> events) {
// Events from ADAL will be sent to this callback
for(Map.Entry<String, String> entry: events.entrySet()) {
Log.d(TAG, entry.getKey() + ": " + entry.getValue());
}
}
}, sTelemetryAggregationIsRequired);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
mainLayt = (LinearLayout) findViewById(R.id.activity_main_login);
Glide.with(this).load(R.drawable.fulton_bg).into(new SimpleTarget<Drawable>() {
@Override
public void onResourceReady(Drawable resource, Transition<? super Drawable> transition) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
mainLayt.setBackground(resource);
}
}
});
mAuthContext = new AuthenticationContext(getApplicationContext(), AUTHORITY, false);
/* Instantiate handler which can invoke interactive sign-in to get the Resource
* sIntSignInInvoked ensures interactive sign-in is invoked one at a time */
mAcquireTokenHandler = new Handler(Looper.getMainLooper()){
@Override
public void handleMessage(Message msg) {
if( sIntSignInInvoked.compareAndSet(false, true)) {
if (msg.what == MSG_INTERACTIVE_SIGN_IN_PROMPT_AUTO){
mAuthContext.acquireToken(getActivity(), RESOURCE_ID, CLIENT_ID, REDIRECT_URI, PromptBehavior.Always, getAuthInteractiveCallback());
}else if(msg.what == MSG_INTERACTIVE_SIGN_IN_PROMPT_ALWAYS){
mAuthContext.acquireToken(getActivity(), RESOURCE_ID, CLIENT_ID, REDIRECT_URI, PromptBehavior.Always, getAuthInteractiveCallback());
}
}
}
};
/* ADAL Logging callback setup */
Logger.getInstance().setExternalLogger(new Logger.ILogger() {
@Override
public void Log(String tag, String message, String additionalMessage, Logger.LogLevel level, ADALError errorCode) {
// You can filter the logs depending on level or errorcode.
Log.d(TAG, message + " " + additionalMessage);
}
});
/*Attempt an acquireTokenSilent call to see if we're signed in*/
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
String userId = preferences.getString(USER_ID, "");
if(!TextUtils.isEmpty(userId)){
mAuthContext.acquireTokenSilentAsync(RESOURCE_ID, CLIENT_ID, userId, getAuthSilentCallback());
}else {
mAuthContext.getCache().removeAll();
}
CheckLoginValues();
}
private void CheckLoginValues() {
String sysId = PrefManager.getSharedPref(LoginChooseActivity.this, PrefManager.PREFERENCE_USER_SYS_ID);
if (!TextUtils.isEmpty(sysId)) {
/*Send broadcast to start SyncService*/
Intent intent = new Intent(Constants.APPLICATION_BROADCAST_INTENT);
intent.putExtra(Constants.APPLICATION_BROADCAST_DATA_ACTION, Constants.ACTION_SYNC);
LocalBroadcastManager.getInstance(LoginChooseActivity.this).sendBroadcast(intent);
Bundle bundle = getIntent().getExtras();
if(bundle != null) {
int requestCode = bundle.getInt(Constants.DATA_KEY_LOGIN_REQUEST_CODE);
if (requestCode == Constants.LOGIN_SCREEN_REQUEST_CODE) {
setResult(Constants.LOGIN_SCREEN_REQUEST_CODE, new Intent());
} else {
startActivity(new Intent(LoginChooseActivity.this, HomeScreen.class));
}
} else {
startActivity(new Intent(LoginChooseActivity.this, HomeScreen.class));
}
isLogin = true;
finish();
}else {
if (NetworkConnectivity.haveNetworkConnection(LoginChooseActivity.this)) {
onCallGraphClicked();
} else {
DialogUtils.showNoConnectionDialog(LoginChooseActivity .this);
}
}
}
@Override
public void onBackPressed() {
super.onBackPressed();
finish();
}
//
// Core Auth methods used by ADAL
// ==================================
// onActivityResult() - handles redirect from System browser
// onCallGraphClicked() - attempts to get tokens for graph, if it succeeds calls graph & updates UI
// callGraphAPI() - called on successful token acquisition which makes an HTTP request to graph
// onSignOutClicked() - Signs user out of the app & updates UI
//
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
mAuthContext.onActivityResult(requestCode, resultCode, data);
}
/*
* End user clicked call Graph API button, time for Auth
* Use ADAL to get an Access token for the Microsoft Graph API
*/
private void onCallGraphClicked() {
mAcquireTokenHandler.sendEmptyMessage(MSG_INTERACTIVE_SIGN_IN_PROMPT_AUTO);
}
private void callGraphAPI() {
mProgressDlg = new ProgressDialog(LoginChooseActivity.this);
mProgressDlg.setMessage(getString(R.string.loading_string));
mProgressDlg.show();
mProgressDlg.setCancelable(false);
Log.d(TAG, "Starting volley request to graph");
/* Make sure we have a token to send to graph */
if (mAuthResult.getAccessToken() == null) {return;}
RequestQueue queue = Volley.newRequestQueue(this);
JSONObject parameters = new JSONObject();
try {
parameters.put("key", "value");
} catch (Exception e) {
Log.d(TAG, "Failed to put parameters: " + e.toString());
}
final JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, MSGRAPH_URL,
parameters,new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
mProgressDlg.dismiss();
/* Successfully called graph, process data and send to UI */
Log.d(TAG, "Response: " + response.toString());
JSONObject root = null;
try {
root = new JSONObject(response.toString());
String userLoginName = root.getString("givenName");
PrefManager.setSharedPref(LoginChooseActivity.this, PrefManager.PREFERENCE_USER_FULL_NAME, userLoginName);
/*Send broadcast to start SyncService*/
if(!isLogin){
new LoginDetailsSendToServer().execute();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
mProgressDlg.dismiss();
Log.d(TAG, "Error: " + error.toString());
}
}) {
@Override
public Map<String, String> getHeaders() {
Map<String, String> headers = new HashMap<>();
headers.put("Authorization", "Bearer " + mAuthResult.getAccessToken());
return headers;
}
};
Log.d(TAG, "Adding HTTP GET to Queue, Request: " + request.toString());
request.setRetryPolicy(new DefaultRetryPolicy(
3000,
DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
queue.add(request);
}
private void onSignOutClicked() {
// End user has clicked the Sign Out button
// Kill the token cache
// Optionally call the signout endpoint to fully sign out the user account
mAuthContext.getCache().removeAll();
// updateSignedOutUI();
}
//
// UI Helper methods
// ================================
// updateGraphUI() - Sets graph response in UI
// updateSuccessUI() - Updates UI when token acquisition succeeds
// updateSignedOutUI() - Updates UI when app sign out succeeds
//
private void updateGraphUI(JSONObject response) {
// Called on success from /me endpoint
// Writes graph data to the UI
TextView graphText = (TextView) findViewById(R.id.graphData);
graphText.setText(response.toString());
}
@SuppressLint("SetTextI18n")
private void updateSuccessUI() {
// Called on success from /me endpoint
// Removed call Graph API button and paint Sign out
}
@SuppressLint("SetTextI18n")
private void updateSignedOutUI() {
}
//
// ADAL Callbacks
// ======================
// getActivity() - returns activity so we can acquireToken within a callback
// getAuthSilentCallback() - callback defined to handle acquireTokenSilent() case
// getAuthInteractiveCallback() - callback defined to handle acquireToken() case
//
public Activity getActivity() {
return this;
}
/* Callback used in for silent acquireToken calls.
* Looks if tokens are in the cache (refreshes if necessary and if we don't forceRefresh)
* else errors that we need to do an interactive request.
*/
private AuthenticationCallback<AuthenticationResult> getAuthSilentCallback() {
return new AuthenticationCallback<AuthenticationResult>() {
@Override
public void onSuccess(AuthenticationResult authenticationResult) {
if(authenticationResult==null || TextUtils.isEmpty(authenticationResult.getAccessToken())
|| authenticationResult.getStatus()!= AuthenticationResult.AuthenticationStatus.Succeeded){
Log.d(TAG, "Silent acquire token Authentication Result is invalid, retrying with interactive");
/* retry with interactive */
mAcquireTokenHandler.sendEmptyMessage(MSG_INTERACTIVE_SIGN_IN_PROMPT_AUTO);
return;
}
/* Successfully got a token, call graph now */
Log.d(TAG, "Successfully authenticated");
/* Store the mAuthResult */
mAuthResult = authenticationResult;
/* call graph */
callGraphAPI();
/* update the UI to post call graph state */
runOnUiThread(new Runnable() {
@Override
public void run() {
updateSuccessUI();
}
});
}
@Override
public void onError(Exception exception) {
/* Failed to acquireToken */
Log.e(TAG, "Authentication failed: " + exception.toString());
if (exception instanceof AuthenticationException) {
AuthenticationException authException = ((AuthenticationException) exception);
ADALError error = authException.getCode();
logHttpErrors(authException);
/* Tokens expired or no session, retry with interactive */
if (error == ADALError.AUTH_REFRESH_FAILED_PROMPT_NOT_ALLOWED ) {
mAcquireTokenHandler.sendEmptyMessage(MSG_INTERACTIVE_SIGN_IN_PROMPT_AUTO);
}else if(error == ADALError.NO_NETWORK_CONNECTION_POWER_OPTIMIZATION){
/* Device is in Doze mode or App is in stand by mode.
Wake up the app or show an appropriate prompt for the user to take action
More information on this : https://github.com/AzureAD/azure-activedirectory-library-for-android/wiki/Handle-Doze-and-App-Standby */
Log.e(TAG, "Device is in doze mode or the app is in standby mode");
}
return;
}
/* Attempt an interactive on any other exception */
mAcquireTokenHandler.sendEmptyMessage(MSG_INTERACTIVE_SIGN_IN_PROMPT_AUTO);
}
};
}
private void logHttpErrors(AuthenticationException authException){
int httpResponseCode = authException.getServiceStatusCode();
Log.d(TAG , "HTTP Response code: " + authException.getServiceStatusCode());
if(httpResponseCode< 200 || httpResponseCode >300) {
// logging http response headers in case of a http error.
HashMap<String, List<String>> headers = authException.getHttpResponseHeaders();
if (headers != null) {
StringBuilder sb = new StringBuilder();
for (Map.Entry<String, List<String>> entry : headers.entrySet()) {
sb.append(entry.getKey());
sb.append(":");
sb.append(entry.getValue().toString());
sb.append("; ");
}
Log.e(TAG, "HTTP Response headers: " + sb.toString());
}
}
}
/* Callback used for interactive request. If succeeds we use the access
* token to call the Microsoft Graph. Does not check cache
*/
private AuthenticationCallback<AuthenticationResult> getAuthInteractiveCallback() {
return new AuthenticationCallback<AuthenticationResult>() {
@Override
public void onSuccess(AuthenticationResult authenticationResult) {
if(authenticationResult==null || TextUtils.isEmpty(authenticationResult.getAccessToken())
|| authenticationResult.getStatus()!= AuthenticationResult.AuthenticationStatus.Succeeded){
Log.e(TAG, "Authentication Result is invalid");
return;
}
/* Successfully got a token, call graph now */
Log.d(TAG, "Successfully authenticated");
Log.d(TAG, "ID Token: " + authenticationResult.getIdToken());
/* Store the auth result */
mAuthResult = authenticationResult;
/* Store User id to SharedPreferences to use it to acquire token silently later */
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
preferences.edit().putString(USER_ID, authenticationResult.getUserInfo().getUserId()).apply();
/* call graph */
callGraphAPI();
/* update the UI to post call graph state */
runOnUiThread(new Runnable() {
@Override
public void run() {
updateSuccessUI();
}
});
/* set the sIntSignInInvoked boolean back to false */
sIntSignInInvoked.set(false);
}
@Override
public void onError(Exception exception) {
/* Failed to acquireToken */
Log.e(TAG, "Authentication failed: " + exception.toString());
if (exception instanceof AuthenticationException) {
ADALError error = ((AuthenticationException)exception).getCode();
if(error==ADALError.AUTH_FAILED_CANCELLED){
Log.e(TAG, "The user cancelled the authorization request");
}else if(error== ADALError.AUTH_FAILED_NO_TOKEN){
// In this case ADAL has found a token in cache but failed to retrieve it.
// Retry interactive with Prompt.Always to ensure we do an interactive sign in
mAcquireTokenHandler.sendEmptyMessage(MSG_INTERACTIVE_SIGN_IN_PROMPT_ALWAYS);
}else if(error == ADALError.NO_NETWORK_CONNECTION_POWER_OPTIMIZATION){
/* Device is in Doze mode or App is in stand by mode.
Wake up the app or show an appropriate prompt for the user to take action
More information on this : https://github.com/AzureAD/azure-activedirectory-library-for-android/wiki/Handle-Doze-and-App-Standby */
Log.e(TAG, "Device is in doze mode or the app is in standby mode");
}
}
/* set the sIntSignInInvoked boolean back to false */
sIntSignInInvoked.set(false);
}
};
}
private class LoginDetailsSendToServer extends AsyncTask<Void, Integer, Integer> {
private ProgressDialog progressDialog;
private static final int USER_DETAIL = 1;
private int apiStatus;
@Override
protected void onPreExecute() {
super.onPreExecute();
progressDialog = new ProgressDialog(LoginChooseActivity.this);
progressDialog.setMessage(getString(R.string.loading_string));
progressDialog.show();
progressDialog.setCancelable(false);
}
@Override
protected Integer doInBackground(Void... params) {
LoginApiManager.submitLoginValues(LoginApiResponse.Json.PASSWORD, Constants.LOGIN_CLIENT_ID, Constants
.LOGIN_CLIENT_SECRET, Constants.FULTON_LOGIN_USERNAME,Constants.FULTON_LOGIN_PASSWORD, new GetUserLoginApiListener() {
@Override
public void onDoneApiCall(LoginApiResponse loginApiResponse) {
apiStatus = API_SUCCESS_USER_LOGIN;
publishProgress(USER_DETAIL);
/*Save access token in Preference*/
PrefManager.setSharedPref(LoginChooseActivity.this, PrefManager.PREFERENCE_ACCESS_TOKEN, loginApiResponse.getAccessToken());
PrefManager.setSharedPref(LoginChooseActivity.this, PrefManager.PREFERENCE_REFRESH_TOKEN, loginApiResponse.getRefreshToken());
UserApiManager.getUserDetailResponse(LoginChooseActivity.this, Constants.FULTON_LOGIN_USERNAME, new GetUserDetailApiListener() {
@Override
public void onDoneApiCall(List<UserApiValues> userValues) {
mUserDetails = userValues;
if(Util.isNotificationsItemEnabled()) {
UserApiManager.putDeviceRegistration(LoginChooseActivity.this, userValues.get(0).getSysId(), new PutDeviceRegistrationApiListener() {
@Override
public void onDoneApiCall() {
apiStatus = API_SUCCESS_USER_DETAIL;
}
@Override
public void onFailApiCall() {
apiStatus = API_FAIL_USER_DETAIL;
}
});
} else {
apiStatus = API_SUCCESS_USER_DETAIL;
}
}
@Override
public void onFailApiCall() {
apiStatus = API_FAIL_USER_DETAIL;
}
});
}
@Override
public void onFailApiCall() {
apiStatus = API_FAIL_USER_LOGIN;
}
});
return apiStatus;
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
if(values[0] == USER_DETAIL) {
// progressDialog.setMessage(getString(R.string.login_screen_getting_user_detail_loading_string));
}
}
@Override
protected void onPostExecute(Integer syncStatus) {
super.onPostExecute(syncStatus);
if (progressDialog != null && progressDialog.isShowing()) {
progressDialog.dismiss();
}
if (syncStatus == API_SUCCESS_USER_DETAIL) {
if (mUserDetails != null) {
isLogin = true;
if (((CatalogueApplication) getApplication()).isNetConnected()) {
ChatBotHistoryManager.delete();
String generateRandomStrPharma = GenerateRandomString.randomString(30);
PrefManager.setSharedPref(LoginChooseActivity.this, PrefManager.SESSION_ID, generateRandomStrPharma);
} else {
DialogUtils.showNoConnectionDialog(LoginChooseActivity.this);
}
String generateRandoStrPharma = GenerateRandomString.randomString(30);
PrefManager.setSharedPref(LoginChooseActivity.this, PrefManager.SESSION_ID, generateRandoStrPharma);
String firstName = mUserDetails.get(0).getFirstName();
String lastName = mUserDetails.get(0).getLastName();
String sysid = mUserDetails.get(0).getSysId();
String userFullName = mUserDetails.get(0).getFullName();
String userId = mUserDetails.get(0).getUserId();
String userEmailId = mUserDetails.get(0).getUserEmailId();
if(Util.isChatItemEnabled()) {
/*Start Chat Local DB Part*/
//Here we'll save logged in user detail in local DB for chat history.
ChatBotUser localChatBotUser = ChatBotUserManager.getChatBotUsersByUserSysId(sysid);
if (localChatBotUser == null) {
/*Clears all data from CHAT_BOT_HISTORY and CHAT_BOT_USER tables*/
ChatBotHistoryManager.deleteAllRows();
ChatBotUserManager.deleteAllRows();
/*Save Logged in user in local db for chat screen*/
ChatBotUser chatBotUser = ChatBotUser.ChatBotUserBuilder.aChatBotUser()
.setUserSysId(sysid)
.setName(firstName)
.build();
ChatBotUserManager.save(chatBotUser);
} else {//Update the name of user
localChatBotUser.setName(firstName);
ChatBotUserManager.update(localChatBotUser);
}
}
/*End Chat Local DB Part*/
PrefManager.setSharedPref(LoginChooseActivity.this, PrefManager.PREFERENCE_USER_FIRST_NAME, firstName);
PrefManager.setSharedPref(LoginChooseActivity.this, PrefManager.PREFERENCE_USER_LAST_NAME, lastName);
PrefManager.setSharedPref(LoginChooseActivity.this, PrefManager.PREFERENCE_USER_SYS_ID, sysid);
/*For pre fill value in variable form*/
PrefManager.setSharedPref(LoginChooseActivity.this, PrefManager.PREFERENCE_USER_ID, userId);
PrefManager.setSharedPref(LoginChooseActivity.this, PrefManager.PREFERENCE_USER_EMAIL_ID, userEmailId);
// /*Send broadcast to start SyncService*/
Intent intent = new Intent(Constants.APPLICATION_BROADCAST_INTENT);
intent.putExtra(Constants.APPLICATION_BROADCAST_DATA_ACTION, Constants.ACTION_SYNC);
LocalBroadcastManager.getInstance(LoginChooseActivity.this).sendBroadcast(intent);
Bundle bundle = getIntent().getExtras();
if(bundle != null) {
int requestCode = bundle.getInt(Constants.DATA_KEY_LOGIN_REQUEST_CODE);
if (requestCode == Constants.LOGIN_SCREEN_REQUEST_CODE) {
startActivity(new Intent(LoginChooseActivity.this, ChatActivity.class));
} else {
startActivity(new Intent(LoginChooseActivity.this, HomeScreen.class));
}
} else {
startActivity(new Intent(LoginChooseActivity.this, HomeScreen.class));
}
//
} else {
Util.simpleAlert(LoginChooseActivity.this,getResources().getString(R.string.user_detail_not_available));
}
} else if (syncStatus == API_FAIL_USER_LOGIN) {
Util.simpleAlert(LoginChooseActivity.this,getResources().getString(R.string.login_screen_invalid_username_and_password_string));
} else if (syncStatus == API_FAIL_USER_DETAIL) {
Util.simpleAlert(LoginChooseActivity.this,getResources().getString(R.string.failed_to_fetch_user_detail_string));
}
}
}
}
......@@ -42,7 +42,7 @@ import butterknife.ButterKnife;
import butterknife.OnClick;
/**
* Created by Kunj on 11/8/16.
* Created by Krishna on 16/10/19.
*/
public class LoginScreen extends Activity {
......@@ -78,7 +78,7 @@ public class LoginScreen extends Activity {
switch (keyCode) {
case KeyEvent.KEYCODE_DPAD_CENTER:
case KeyEvent.KEYCODE_ENTER:
callLoginAPI(false);
callLoginAPI();
return true;
default:
break;
......@@ -114,22 +114,6 @@ public class LoginScreen extends Activity {
Util.sendScreenName(tracker, getString(R.string.login_screen_string));
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == Constants.LOGIN_SCREEN_OTP_REQUEST_CODE){
if(data!=null && data.getExtras()!=null){
String message = data.getExtras().getString(Constants.MESSAGE);
if(message.equalsIgnoreCase(Constants.RESPONSE_SUCCESS)){
callLoginAPI(false);
}else{
Toast.makeText(this,"Something went Wrong",Toast.LENGTH_LONG).show();
}
}
}
}
private void CheckLoginValues() {
String sysId = PrefManager.getSharedPref(LoginScreen.this, PrefManager.PREFERENCE_USER_SYS_ID);
if (!TextUtils.isEmpty(sysId)) {
......@@ -153,7 +137,7 @@ public class LoginScreen extends Activity {
}
}
private void callLoginAPI(boolean withOtp) {
private void callLoginAPI() {
String userNameString = mUserNameEditText.getText().toString().trim();
String passwordString = mPasswordEditText.getText().toString().trim();
......@@ -166,26 +150,19 @@ public class LoginScreen extends Activity {
if (!TextUtils.isEmpty(userNameString) && !TextUtils.isEmpty(passwordString)) {
KeyboardUtil.hideKeyboard(LoginScreen.this);
if (mApplication.isNetConnected()) {
if(withOtp){
launchOptValidationScreen();
}else{
new LoginDetailsSendToServer().execute(mUserNameEditText.getText().toString().trim(), mPasswordEditText.getText().toString().trim());
}
new LoginDetailsSendToServer().execute(mUserNameEditText.getText().toString().trim(), mPasswordEditText.getText().toString().trim());
} else {
DialogUtils.showNoConnectionDialog(LoginScreen.this);
}
}
}
@OnClick(R.id.login_screen_login_text_view)
void onLoginClicked() {
callLoginAPI();
private void launchOptValidationScreen(){
Intent intent = new Intent(LoginScreen.this,OtpValidationActivity.class);
startActivityForResult(intent,Constants.LOGIN_SCREEN_OTP_REQUEST_CODE);
}
private class LoginDetailsSendToServer extends AsyncTask<String, Integer, Integer> {
private ProgressDialog progressDialog;
private static final int USER_DETAIL = 1;
......@@ -317,7 +294,7 @@ public class LoginScreen extends Activity {
PrefManager.setSharedPref(LoginScreen.this, PrefManager.PREFERENCE_USER_EMAIL_ID, userEmailId);
/*Send broadcast to start SyncService*/
/*Send broadcast to start SyncService*/
Intent intent = new Intent(Constants.APPLICATION_BROADCAST_INTENT);
intent.putExtra(Constants.APPLICATION_BROADCAST_DATA_ACTION, Constants.ACTION_SYNC);
LocalBroadcastManager.getInstance(LoginScreen.this).sendBroadcast(intent);
......
package com.vsoft.vera.ui;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.content.LocalBroadcastManager;
import android.text.TextUtils;
import android.view.View;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.Toast;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.target.SimpleTarget;
import com.bumptech.glide.request.transition.Transition;
import com.vsoft.vera.CatalogueApplication;
import com.vsoft.vera.R;
import com.vsoft.vera.api.listeners.get.GetLiveAgentApiListener;
import com.vsoft.vera.api.listeners.get.GetUserDetailApiListener;
import com.vsoft.vera.api.listeners.get.GetUserLoginApiListener;
import com.vsoft.vera.api.listeners.get.GetValidateOtpApiListener;
import com.vsoft.vera.api.listeners.post.PostOtpApiListener;
import com.vsoft.vera.api.listeners.put.PutDeviceRegistrationApiListener;
import com.vsoft.vera.api.managers.LoginApiManager;
import com.vsoft.vera.api.managers.OtpApiManager;
import com.vsoft.vera.api.managers.UserApiManager;
import com.vsoft.vera.api.pojos.LoginApiResponse;
import com.vsoft.vera.db.managers.ChatBotHistoryManager;
import com.vsoft.vera.db.managers.ChatBotUserManager;
import com.vsoft.vera.db.models.ChatBotUser;
import com.vsoft.vera.db.models.UserApiValues;
import com.vsoft.vera.enums.SyncStatus;
import com.vsoft.vera.utils.Constants;
import com.vsoft.vera.utils.DialogUtils;
import com.vsoft.vera.utils.GenerateRandomString;
import com.vsoft.vera.utils.KeyboardUtil;
import com.vsoft.vera.utils.PrefManager;
import com.vsoft.vera.utils.Util;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
public class OtpValidationActivity extends Activity {
@BindView(R.id.otp_screen_phone_edit_text) EditText mPhoneEditText;
@BindView(R.id.otp_screen_otp_edit_text) EditText mOTPEditText;
@BindView(R.id.phone_validate_layout) RelativeLayout phone_layout;
@BindView(R.id.otp_validate_layout) RelativeLayout otp_validate_layout;
private CatalogueApplication mApplication;
private String phoneString = null;
private static final int API_SUCCESS_USER_LOGIN = 1;
private static final int API_FAIL_USER_LOGIN = 2;
private static final int API_SUCCESS_USER_DETAIL = 3;
private static final int API_FAIL_USER_DETAIL = 4;
private List<UserApiValues> mUserDetails;
private LinearLayout mainLayt;
String userFullName;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_otp_validation);
mainLayt = (LinearLayout) findViewById(R.id.activity_main_lyt);
Glide.with(this).load(R.drawable.fulton_bg).into(new SimpleTarget<Drawable>() {
@Override
public void onResourceReady(Drawable resource, Transition<? super Drawable> transition) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
mainLayt.setBackground(resource);
}
}
});
ButterKnife.bind(this);
mApplication = (CatalogueApplication) getApplication();
// new LoginDetailsSendToServer().execute();
}
@OnClick(R.id.otp_screen_text_view)
void onLoginClicked() {
callOtpAPI();
}
@OnClick(R.id.otp_screen_validate_text_view)
void onValidateClicked(){
callValidateOtpAPI();
}
private void callOtpAPI() {
phoneString = mPhoneEditText.getText().toString().trim();
if (TextUtils.isEmpty(phoneString)) {
mPhoneEditText.setError(getResources().getString(R.string.phone_no_error));
} else if (!TextUtils.isEmpty(phoneString) && phoneString.length() >= 10 && phoneString.length() <=20) {
KeyboardUtil.hideKeyboard(OtpValidationActivity.this);
if (mApplication.isNetConnected()) {
new generateOtp().execute(phoneString);
} else {
DialogUtils.showNoConnectionDialog(OtpValidationActivity.this);
}
}
}
private void callValidateOtpAPI() {
String otpCode = mOTPEditText.getText().toString().trim();
if (TextUtils.isEmpty(otpCode)) {
mOTPEditText.setError(getResources().getString(R.string.otp_error));
} else if(!TextUtils.isEmpty(otpCode) && otpCode.length() <=8) {
KeyboardUtil.hideKeyboard(OtpValidationActivity.this);
if (mApplication.isNetConnected()) {
new validateOtp().execute(phoneString, otpCode);
} else {
DialogUtils.showNoConnectionDialog(OtpValidationActivity.this);
}
}
}
private class generateOtp extends AsyncTask<String, Integer, Integer> {
private ProgressDialog progressDialog;
private String apiMessage="Something went Wrong";
private int apiStatus=0;
@Override
protected void onPreExecute() {
super.onPreExecute();
progressDialog = new ProgressDialog(OtpValidationActivity.this);
progressDialog.setMessage(getString(R.string.generating_otp));
progressDialog.show();
progressDialog.setCancelable(false);
}
@Override
protected Integer doInBackground(String... params) {
String phoneString = params[0];
OtpApiManager.getOTP(phoneString, new PostOtpApiListener() {
@Override
public void onDoneApiCall(String message) {
apiMessage = message;
apiStatus = 1;
}
@Override
public void onFailApiCall(String message) {
apiMessage = message;
apiStatus = 0;
}
});
return apiStatus;
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
}
@Override
protected void onPostExecute(Integer status) {
super.onPostExecute(status);
if (progressDialog != null && progressDialog.isShowing()) {
progressDialog.dismiss();
}
if(apiStatus==1){ // success
showPhoneLayout(false);
}else{
showPhoneLayout(true);
}
Toast.makeText(OtpValidationActivity.this,apiMessage,Toast.LENGTH_LONG).show();
}
}
@Override
public void onBackPressed() {
super.onBackPressed();
finish();
}
private class validateOtp extends AsyncTask<String, Integer, String>{
private ProgressDialog progressDialog;
private String apiMessage="Something went Wrong";
private int apiStatus=0;
@Override
protected void onPreExecute() {
super.onPreExecute();
progressDialog = new ProgressDialog(OtpValidationActivity.this);
progressDialog.setMessage(getString(R.string.validating_otp));
progressDialog.show();
progressDialog.setCancelable(false);
}
@Override
protected String doInBackground(String... params) {
String phoneString = params[0];
String otpCode = params[1];
OtpApiManager.validateOTP(phoneString, otpCode,new GetValidateOtpApiListener() {
@Override
public void onDoneApiCall(String message) {
apiMessage = message;
apiStatus = 1;
}
@Override
public void onFailApiCall(String message) {
apiMessage = message;
apiStatus = 0;
}
});
return apiMessage;
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
}
@Override
protected void onPostExecute(String message) {
super.onPostExecute(message);
if (progressDialog != null && progressDialog.isShowing()) {
progressDialog.dismiss();
}
if(apiStatus==1){
PrefManager.setSharedPref(OtpValidationActivity.this, PrefManager.MOBILE_NUMBER, phoneString);
new LoginDetailsSendToServer().execute();
}else{
Toast.makeText(OtpValidationActivity.this,apiMessage,Toast.LENGTH_LONG).show();
}
}
}
private void showPhoneLayout(boolean show){
if(show){
phone_layout.setVisibility(View.VISIBLE);
otp_validate_layout.setVisibility(View.GONE);
}else{
phone_layout.setVisibility(View.GONE);
otp_validate_layout.setVisibility(View.VISIBLE);
}
}
private class LoginDetailsSendToServer extends AsyncTask<Void, Integer, Integer> {
private ProgressDialog progressDialog;
private static final int USER_DETAIL = 1;
private int apiStatus;
@Override
protected void onPreExecute() {
super.onPreExecute();
progressDialog = new ProgressDialog(OtpValidationActivity.this);
progressDialog.setMessage(getString(R.string.login_screen_logging_in_loading_string));
progressDialog.show();
progressDialog.setCancelable(false);
}
@Override
protected Integer doInBackground(Void... params) {
LoginApiManager.submitLoginValues(LoginApiResponse.Json.PASSWORD, Constants.LOGIN_CLIENT_ID, Constants
.LOGIN_CLIENT_SECRET,Constants.FULTON_LOGIN_USERNAME,Constants.FULTON_LOGIN_PASSWORD, new GetUserLoginApiListener() {
@Override
public void onDoneApiCall(LoginApiResponse loginApiResponse) {
apiStatus = API_SUCCESS_USER_LOGIN;
publishProgress(USER_DETAIL);
/*Save access token in Preference*/
PrefManager.setSharedPref(OtpValidationActivity.this, PrefManager.PREFERENCE_ACCESS_TOKEN, loginApiResponse.getAccessToken());
PrefManager.setSharedPref(OtpValidationActivity.this, PrefManager.PREFERENCE_REFRESH_TOKEN, loginApiResponse.getRefreshToken());
UserApiManager.getUserDetailResponse(OtpValidationActivity.this, Constants.FULTON_LOGIN_USERNAME, new GetUserDetailApiListener() {
@Override
public void onDoneApiCall(List<UserApiValues> userValues) {
mUserDetails = userValues;
if(Util.isNotificationsItemEnabled()) {
UserApiManager.putDeviceRegistration(OtpValidationActivity.this, userValues.get(0).getSysId(), new PutDeviceRegistrationApiListener() {
@Override
public void onDoneApiCall() {
apiStatus = API_SUCCESS_USER_DETAIL;
}
@Override
public void onFailApiCall() {
apiStatus = API_FAIL_USER_DETAIL;
}
});
} else {
apiStatus = API_SUCCESS_USER_DETAIL;
}
}
@Override
public void onFailApiCall() {
apiStatus = API_FAIL_USER_DETAIL;
}
});
}
@Override
public void onFailApiCall() {
apiStatus = API_FAIL_USER_LOGIN;
}
});
return apiStatus;
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
if(values[0] == USER_DETAIL) {
// progressDialog.setMessage(getString(R.string.login_screen_getting_user_detail_loading_string));
}
}
@Override
protected void onPostExecute(Integer syncStatus) {
super.onPostExecute(syncStatus);
if (progressDialog != null && progressDialog.isShowing()) {
progressDialog.dismiss();
}
if (syncStatus == API_SUCCESS_USER_DETAIL) {
if (mUserDetails != null) {
if (((CatalogueApplication) getApplication()).isNetConnected()) {
ChatBotHistoryManager.delete();
String generateRandomStrPharma = GenerateRandomString.randomString(30);
PrefManager.setSharedPref(OtpValidationActivity.this, PrefManager.SESSION_ID, generateRandomStrPharma);
} else {
DialogUtils.showNoConnectionDialog(OtpValidationActivity.this);
}
String generateRandoStrPharma = GenerateRandomString.randomString(30);
PrefManager.setSharedPref(OtpValidationActivity.this, PrefManager.SESSION_ID, generateRandoStrPharma);
String firstName = mUserDetails.get(0).getFirstName();
String lastName = mUserDetails.get(0).getLastName();
String sysid = mUserDetails.get(0).getSysId();
userFullName = mUserDetails.get(0).getFullName();
String userId = mUserDetails.get(0).getUserId();
String userEmailId = mUserDetails.get(0).getUserEmailId();
if(Util.isChatItemEnabled()) {
/*Start Chat Local DB Part*/
//Here we'll save logged in user detail in local DB for chat history.
ChatBotUser localChatBotUser = ChatBotUserManager.getChatBotUsersByUserSysId(sysid);
if (localChatBotUser == null) {
/*Clears all data from CHAT_BOT_HISTORY and CHAT_BOT_USER tables*/
ChatBotHistoryManager.deleteAllRows();
ChatBotUserManager.deleteAllRows();
/*Save Logged in user in local db for chat screen*/
ChatBotUser chatBotUser = ChatBotUser.ChatBotUserBuilder.aChatBotUser()
.setUserSysId(sysid)
.setName(firstName)
.build();
ChatBotUserManager.save(chatBotUser);
} else {//Update the name of user
localChatBotUser.setName(firstName);
ChatBotUserManager.update(localChatBotUser);
}
}
/*End Chat Local DB Part*/
PrefManager.setSharedPref(OtpValidationActivity.this, PrefManager.PREFERENCE_USER_FIRST_NAME, firstName);
PrefManager.setSharedPref(OtpValidationActivity.this, PrefManager.PREFERENCE_USER_LAST_NAME, lastName);
/*For pre fill value in variable form*/
PrefManager.setSharedPref(OtpValidationActivity.this, PrefManager.PREFERENCE_USER_ID, userId);
PrefManager.setSharedPref(OtpValidationActivity.this, PrefManager.PREFERENCE_USER_SYS_ID, sysid);
new GetyUserSysIDAsync().execute();
} else {
Util.simpleAlert(OtpValidationActivity.this,getResources().getString(R.string.user_detail_not_available));
}
} else if (syncStatus == API_FAIL_USER_LOGIN) {
Util.simpleAlert(OtpValidationActivity.this,getResources().getString(R.string.login_screen_invalid_username_and_password_string));
} else if (syncStatus == API_FAIL_USER_DETAIL) {
Util.simpleAlert(OtpValidationActivity.this,getResources().getString(R.string.failed_to_fetch_user_detail_string));
}
}
}
private class GetyUserSysIDAsync extends AsyncTask<Void, Void, SyncStatus> {
private ProgressDialog progressDialog;
private SyncStatus syncStatus = SyncStatus.FAIL;
String userSysId;
String accessToken;
String email;
@Override
protected void onPreExecute() {
super.onPreExecute();
progressDialog = new ProgressDialog(OtpValidationActivity.this);
progressDialog.setMessage(getString(R.string.login_screen_logging_in_loading_string));
progressDialog.show();
progressDialog.setCancelable(false);
accessToken = PrefManager.getSharedPref(OtpValidationActivity.this, PrefManager.PREFERENCE_ACCESS_TOKEN);
email = "kkonarski@vsoftconsulting.com";
PrefManager.setSharedPref(OtpValidationActivity.this, PrefManager.PREFERENCE_USER_EMAIL_ID, email);
}
@Override
protected SyncStatus doInBackground(Void... params) {
UserApiManager.getUserSysId(OtpValidationActivity.this,accessToken,email,new GetLiveAgentApiListener() {
@Override
public void onDoneApiCall(String url) {
userSysId = url;
syncStatus = SyncStatus.SUCCESS;
}
@Override
public void onFailApiCall() {
syncStatus = SyncStatus.FAIL;
}
});
return syncStatus;
}
@Override
protected void onPostExecute(SyncStatus syncStatus) {
super.onPostExecute(syncStatus);
if (progressDialog != null && progressDialog.isShowing()) {
progressDialog.dismiss();
}
if (syncStatus == SyncStatus.SUCCESS) {
if(userSysId != null){
PrefManager.setSharedPref(OtpValidationActivity.this, PrefManager.PREFERENCE_DYNAMIC_USER_SYS_ID, userSysId);
/*Send broadcast to start SyncService*/
Intent intent = new Intent(Constants.APPLICATION_BROADCAST_INTENT);
intent.putExtra(Constants.APPLICATION_BROADCAST_DATA_ACTION, Constants.ACTION_SYNC);
LocalBroadcastManager.getInstance(OtpValidationActivity.this).sendBroadcast(intent);
Bundle bundle = getIntent().getExtras();
if(bundle != null) {
int requestCode = bundle.getInt(Constants.DATA_KEY_LOGIN_REQUEST_CODE);
if (requestCode == Constants.LOGIN_SCREEN_REQUEST_CODE) {
startActivity(new Intent(OtpValidationActivity.this, ChatActivity.class));
} else {
Intent homeIntent = new Intent(OtpValidationActivity.this, HomeScreen.class);
homeIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(homeIntent);
}
} else {
Intent homeIntent = new Intent(OtpValidationActivity.this, HomeScreen.class);
homeIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(homeIntent);
}
}else {
Util.simpleAlert(OtpValidationActivity.this,getResources().getString(R.string.user_detail_not_available));
}
} else if (syncStatus == SyncStatus.FAIL) {
Util.simpleAlert(OtpValidationActivity.this,getResources().getString(R.string.failed_to_fetch_user_detail_string));
}
}
}
}
......@@ -11,12 +11,10 @@ public class PrefManager {
public static final String PREFERENCE_USER_FIRST_NAME = "firstName";
public static final String PREFERENCE_USER_LAST_NAME = "lastName";
public static final String PREFERENCE_USER_SYS_ID = "sysId";
public static final String PREFERENCE_DYNAMIC_USER_SYS_ID = "dynamic_sysId";
public static final String PREFERENCE_USER_FULL_NAME = "full_name";
public static final String PREFERENCE_USER_ID = "user_id";
public static final String PREFERENCE_USER_EMAIL_ID = "user_email_id";
public static final String SESSION_ID = "session_id";
public static final String MOBILE_NUMBER = "mobile_number";
//Chat Server Url
public static final String PREFERENCE_CHAT_SERVER_URL = "chat_server_url";
......
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<!-- <solid android:color="@color/button_bg" />-->
<!-- <corners android:radius="10dip" />-->
<!-- <stroke-->
<!-- android:width="1dp"-->
<!-- android:color="@color/button_bg" />-->
<corners
android:radius="0dp"
/>
<gradient
android:angle="45"
android:centerX="35%"
android:startColor="#e5e5e5"
android:centerColor="#7f7f7f"
android:endColor="#b2b2b2"
android:type="linear"
/>
<padding
android:left="0dp"
android:top="0dp"
android:right="0dp"
android:bottom="0dp"
/>
<size
android:width="200dp"
android:height="400dp"
/>
</shape>
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M12,12c2.21,0 4,-1.79 4,-4s-1.79,-4 -4,-4 -4,1.79 -4,4 1.79,4 4,4zM12,14c-2.67,0 -8,1.34 -8,4v2h16v-2c0,-2.66 -5.33,-4 -8,-4z"/>
</vector>
......@@ -16,9 +16,9 @@
<gradient
android:angle="45"
android:centerX="35%"
android:centerColor="#6699c8"
android:startColor="#7faad1"
android:endColor="#1966ad"
android:startColor="#303030"
android:centerColor="#666666"
android:endColor="#303030"
android:type="linear"
/>
<padding
......
......@@ -39,7 +39,7 @@
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_centerVertical="true"
android:text="FULTON COUNTY"
android:text="@string/app_name"
android:textColor="@color/screen_bg_color_white" />
<ImageView
......

6.88 KB | W: | H:

1.33 KB | W: | H:

app/src/main/res/mipmap-hdpi/ic_launcher.png
app/src/main/res/mipmap-hdpi/ic_launcher.png
app/src/main/res/mipmap-hdpi/ic_launcher.png
app/src/main/res/mipmap-hdpi/ic_launcher.png
  • 2-up
  • Swipe
  • Onion skin

10.5 KB | W: | H:

1.58 KB | W: | H:

app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
  • 2-up
  • Swipe
  • Onion skin

6.88 KB | W: | H:

3.09 KB | W: | H:

app/src/main/res/mipmap-hdpi/ic_launcher_round.png
app/src/main/res/mipmap-hdpi/ic_launcher_round.png
app/src/main/res/mipmap-hdpi/ic_launcher_round.png
app/src/main/res/mipmap-hdpi/ic_launcher_round.png
  • 2-up
  • Swipe
  • Onion skin

3.94 KB | W: | H:

941 Bytes | W: | H:

app/src/main/res/mipmap-mdpi/ic_launcher.png
app/src/main/res/mipmap-mdpi/ic_launcher.png
app/src/main/res/mipmap-mdpi/ic_launcher.png
app/src/main/res/mipmap-mdpi/ic_launcher.png
  • 2-up
  • Swipe
  • Onion skin

5.82 KB | W: | H:

1.01 KB | W: | H:

app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
  • 2-up
  • Swipe
  • Onion skin

3.94 KB | W: | H:

1.93 KB | W: | H:

app/src/main/res/mipmap-mdpi/ic_launcher_round.png
app/src/main/res/mipmap-mdpi/ic_launcher_round.png
app/src/main/res/mipmap-mdpi/ic_launcher_round.png
app/src/main/res/mipmap-mdpi/ic_launcher_round.png
  • 2-up
  • Swipe
  • Onion skin

10.5 KB | W: | H:

1.86 KB | W: | H:

app/src/main/res/mipmap-xhdpi/ic_launcher.png
app/src/main/res/mipmap-xhdpi/ic_launcher.png
app/src/main/res/mipmap-xhdpi/ic_launcher.png
app/src/main/res/mipmap-xhdpi/ic_launcher.png
  • 2-up
  • Swipe
  • Onion skin

16.2 KB | W: | H:

2.16 KB | W: | H:

app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
  • 2-up
  • Swipe
  • Onion skin

10.5 KB | W: | H:

4.48 KB | W: | H:

app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
  • 2-up
  • Swipe
  • Onion skin

18.7 KB | W: | H:

2.86 KB | W: | H:

app/src/main/res/mipmap-xxhdpi/ic_launcher.png
app/src/main/res/mipmap-xxhdpi/ic_launcher.png
app/src/main/res/mipmap-xxhdpi/ic_launcher.png
app/src/main/res/mipmap-xxhdpi/ic_launcher.png
  • 2-up
  • Swipe
  • Onion skin

31.3 KB | W: | H:

3.49 KB | W: | H:

app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png
app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png
app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png
app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png
  • 2-up
  • Swipe
  • Onion skin

18.7 KB | W: | H:

7.14 KB | W: | H:

app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
  • 2-up
  • Swipe
  • Onion skin

28.7 KB | W: | H:

4.05 KB | W: | H:

app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
  • 2-up
  • Swipe
  • Onion skin

50.1 KB | W: | H:

5.19 KB | W: | H:

app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png
app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png
app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png
app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png
  • 2-up
  • Swipe
  • Onion skin

28.7 KB | W: | H:

10.3 KB | W: | H:

app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
  • 2-up
  • Swipe
  • Onion skin
<resources>
<string name="app_name">Fulton-County</string>
<string name="app_name">VERA-2.1</string>
<string name="set_string">Set</string>
<string name="submit_string">Submit</string>
......
......@@ -12,8 +12,8 @@ public class AppConfig {
public static final String LOGIN_CLIENT_ID_RELEASE = "d958eb06b0f3830093781f441d59febc";
public static final String LOGIN_CLIENT_SECRET_RELEASE = "krD*!O}1.8";
public static final String LOGIN_CLIENT_ID_DEBUG = "89cfc0656ce6b30012af8b50316c9376";
public static final String LOGIN_CLIENT_SECRET_DEBUG = ")R+)DZh|,T";
public static final String LOGIN_CLIENT_ID_DEBUG = "0ab7489795c40410d06a70ea1d212df1";
public static final String LOGIN_CLIENT_SECRET_DEBUG = "Cmei6uCRfM";
public static final String LOGIN_CLIENT_ID_STAGING = "091b5d1ea97cd700e4268b90dd5521ca";
public static final String LOGIN_CLIENT_SECRET_STAGING = "+tPJ@jS<;S";
......@@ -61,8 +61,8 @@ public class AppConfig {
/**
* We will hit the below url to get the chat server url.
* */
public static final String CHAT_SERVER_API_URL_RELEASE = "http://52.21.5.26:12814/service_discovery";
public static final String CHAT_SERVER_API_URL_RELEASE = "http://52.21.5.26:12811/service_discovery";
public static final String CHAT_SERVER_API_URL_DEBUG = "http://52.21.5.26:12811/service_discovery";
public static final String CHAT_SERVER_API_URL_STAGING = "http://52.21.5.26:12813/service_discovery";
public static final String CHAT_SERVER_API_URL_STAGING = "http://52.21.5.26:12811/service_discovery";
}
......@@ -2,6 +2,7 @@
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:focusableInTouchMode="true"
android:scrollbarStyle="insideOverlay">
......
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/splash_main_lyt"
......@@ -11,8 +11,10 @@
android:id="@+id/splash_image"
android:layout_gravity="center"
android:layout_width="200dp"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:layout_height="150dp"
/>
</LinearLayout>
\ No newline at end of file
</RelativeLayout>
\ No newline at end of file
<resources>
<string name="app_name">Fulton-County</string>
<string name="app_name">VERA-2.1</string>
<!--home Screen Option-->
<!--Start-->
......
No preview for this file type
[{"outputType":{"type":"APK"},"apkData":{"type":"MAIN","splits":[],"versionCode":1,"versionName":"0.0.6","enabled":true,"outputFile":"app-vportal-debug.apk","fullName":"vportalDebug","baseName":"vportal-debug"},"path":"app-vportal-debug.apk","properties":{}}]
\ No newline at end of file
[{"outputType":{"type":"APK"},"apkData":{"type":"MAIN","splits":[],"versionCode":1,"versionName":"0.2.6","enabled":true,"outputFile":"app-vportal-debug.apk","fullName":"vportalDebug","baseName":"vportal-debug"},"path":"app-vportal-debug.apk","properties":{}}]
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment