Java tutorial
/* * Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * * WSO2 Inc. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except * in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.wso2.iot.nfcprovisioning; import android.app.ProgressDialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.support.v4.content.ContextCompat; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.text.Editable; import android.util.Log; import android.view.KeyEvent; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; import org.json.JSONException; import org.json.JSONObject; import org.wso2.iot.nfcprovisioning.proxy.IdentityProxy; import org.wso2.iot.nfcprovisioning.proxy.beans.CredentialInfo; import org.wso2.iot.nfcprovisioning.proxy.interfaces.APIAccessCallBack; import org.wso2.iot.nfcprovisioning.proxy.interfaces.APIResultCallBack; import org.wso2.iot.nfcprovisioning.beans.ApiRegistrationProfile; import org.wso2.iot.nfcprovisioning.utils.CommonDialogUtils; import org.wso2.iot.nfcprovisioning.utils.CommonUtils; import org.wso2.iot.nfcprovisioning.utils.Constants; import org.wso2.iot.nfcprovisioning.api.DeviceInfo; import org.wso2.iot.nfcprovisioning.utils.AndroidAgentException; import org.wso2.iot.nfcprovisioning.utils.DynamicClientManager; import org.wso2.iot.nfcprovisioning.utils.Preference; import java.util.Map; /** * Activity that captures serverip, username, password and device ownership details * and handles authentication. */ public class AuthenticationActivity extends AppCompatActivity implements APIAccessCallBack, APIResultCallBack { private Button btnSignIn; private EditText etUsername; private EditText etDomain; private EditText etPassword; private EditText etServerIP; private Context context; private String username; private String usernameVal; private String passwordVal; private ProgressDialog progressDialog; private boolean isReLogin = false; private DeviceInfo deviceInfo; private static final String TAG = AuthenticationActivity.class.getSimpleName(); private static final String[] SUBSCRIBED_API = new String[] { "android" }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); context = this; setContentView(R.layout.activity_authentication); deviceInfo = new DeviceInfo(context); etServerIP = (EditText) findViewById(R.id.serverIP); etDomain = (EditText) findViewById(R.id.organization); etUsername = (EditText) findViewById(R.id.username); etPassword = (EditText) findViewById(R.id.password); btnSignIn = (Button) findViewById(R.id.username_sign_in_button); btnSignIn.setOnClickListener(onClickAuthenticate); if (Constants.DEFAULT_HOST != null && !Constants.DEFAULT_HOST.equals("")) { etServerIP.setText(Constants.DEFAULT_HOST); etDomain.setFocusable(true); etDomain.requestFocus(); } else { etServerIP.setFocusable(true); etServerIP.requestFocus(); } if (Preference.hasPreferenceKey(context, Constants.TOKEN_EXPIRED)) { etDomain.setTextColor(ContextCompat.getColor(this, R.color.black)); etUsername.setTextColor(ContextCompat.getColor(this, R.color.black)); etPassword.setFocusable(true); etPassword.requestFocus(); String tenantedUserName = Preference.getString(context, Constants.USERNAME); int tenantSeparator = tenantedUserName.lastIndexOf('@'); etUsername.setText(tenantedUserName.substring(0, tenantSeparator)); etDomain.setText(tenantedUserName.substring(tenantSeparator + 1, tenantedUserName.length())); isReLogin = true; } } @Override protected void onResume() { super.onResume(); if (progressDialog != null) { progressDialog.show(); } } @Override protected void onPause() { super.onPause(); if (progressDialog != null && progressDialog.isShowing()) { progressDialog.dismiss(); } else { progressDialog = null; } } @Override protected void onDestroy() { super.onDestroy(); CommonDialogUtils.stopProgressDialog(progressDialog); progressDialog = null; } private OnClickListener onClickAuthenticate = new OnClickListener() { @Override public void onClick(View view) { if (etServerIP.getText() != null && !etUsername.getText().toString().trim().isEmpty() && etUsername.getText() != null && !etUsername.getText().toString().trim().isEmpty() && etPassword.getText() != null && !etPassword.getText().toString().trim().isEmpty()) { String serverIP = etServerIP.getText().toString().trim(); Preference.putString(context, Constants.PreferenceFlag.IP, serverIP); passwordVal = etPassword.getText().toString().trim(); usernameVal = etUsername.getText().toString().trim(); proceedToAuthentication(); } else { if (etServerIP.getText() != null && etServerIP.getText().toString().trim().isEmpty()) { Toast.makeText(context, getResources().getString(R.string.error_server_ip), Toast.LENGTH_LONG) .show(); } else if (etUsername.getText() != null && etUsername.getText().toString().trim().isEmpty()) { Toast.makeText(context, getResources().getString(R.string.error_username), Toast.LENGTH_LONG) .show(); } else if (etPassword.getText() != null && etPassword.getText().toString().trim().isEmpty()) { Toast.makeText(context, getResources().getString(R.string.error_password), Toast.LENGTH_LONG) .show(); } } } }; private void proceedToAuthentication() { if (etDomain.getText() != null && !etDomain.getText().toString().trim().isEmpty()) { usernameVal += getResources().getString(R.string.intent_extra_at) + etDomain.getText().toString().trim(); } getClientCredentials(); } /** * Start authentication process. */ private void startAuthentication() { // Check network connection availability before calling the API. if (CommonUtils.isNetworkAvailable(context)) { String clientId = Preference.getString(context, Constants.CLIENT_ID); String clientSecret = Preference.getString(context, Constants.CLIENT_SECRET); if (clientId == null || clientSecret == null) { String clientCredentials = Preference.getString(context, getResources().getString(R.string.shared_pref_client_credentials)); if (clientCredentials != null) { try { JSONObject payload = new JSONObject(clientCredentials); clientId = payload.getString(Constants.CLIENT_ID); clientSecret = payload.getString(Constants.CLIENT_SECRET); if (clientId != null && !clientId.isEmpty() && clientSecret != null && !clientSecret.isEmpty()) { initializeIDPLib(clientId, clientSecret); } } catch (JSONException e) { String msg = "error occurred while parsing client credential payload"; Log.e(TAG, msg, e); CommonDialogUtils.stopProgressDialog(progressDialog); showInternalServerErrorMessage(); } } else { String msg = "error occurred while retrieving client credentials"; Log.e(TAG, msg); CommonDialogUtils.stopProgressDialog(progressDialog); showInternalServerErrorMessage(); } } else { initializeIDPLib(clientId, clientSecret); } } else { CommonDialogUtils.stopProgressDialog(progressDialog); CommonDialogUtils.showNetworkUnavailableMessage(context); } } /** * Initialize the Android IDP SDK by passing credentials,client ID and * client secret. * * @param clientKey client id value to access APIs.. * @param clientSecret client secret value to access APIs. */ private void initializeIDPLib(String clientKey, String clientSecret) { String serverIP = Preference.getString(context.getApplicationContext(), Constants.PreferenceFlag.IP); if (serverIP != null && !serverIP.isEmpty()) { String serverURL = serverIP + Constants.OAUTH_ENDPOINT; Editable tenantDomain = etDomain.getText(); if (tenantDomain != null && !tenantDomain.toString().trim().isEmpty()) { username = etUsername.getText().toString().trim() + context.getResources().getString(R.string.intent_extra_at) + tenantDomain.toString().trim(); } else { username = etUsername.getText().toString().trim(); } Preference.putString(context, Constants.CLIENT_ID, clientKey); Preference.putString(context, Constants.CLIENT_SECRET, clientSecret); CredentialInfo info = new CredentialInfo(); info.setClientID(clientKey); info.setClientSecret(clientSecret); info.setUsername(username); info.setPassword(passwordVal); info.setTokenEndPoint(serverURL); //adding device-specific scope String deviceScope = "device_" + deviceInfo.getDeviceId(); info.setScopes(deviceScope); if (tenantDomain != null && !tenantDomain.toString().trim().isEmpty()) { info.setTenantDomain(tenantDomain.toString().trim()); } IdentityProxy.getInstance().init(info, AuthenticationActivity.this, this.getApplicationContext()); } } @Override public void onAPIAccessReceive(String status) { if (status != null) { if (status.trim().equals(Constants.Status.SUCCESSFUL)) { CommonDialogUtils.stopProgressDialog(progressDialog); if (isReLogin) { Preference.removePreference(context, Constants.TOKEN_EXPIRED); loadProvisioningActivity(); } else { Preference.putString(context, Constants.USERNAME, username); Preference.putBoolean(this, Constants.IS_REGISTERED, true); loadProvisioningActivity(); } } else if (status.trim().equals(Constants.Status.AUTHENTICATION_FAILED)) { showAuthenticationError(); // clearing client credentials from shared memory CommonUtils.clearClientCredentials(context); } else if (status.trim().equals(Constants.Status.INTERNAL_SERVER_ERROR)) { showInternalServerErrorMessage(); } else { showAuthCommonErrorMessage(); } } else { showAuthCommonErrorMessage(); } } @Override public void onReceiveAPIResult(Map<String, String> result, int requestCode) { if (requestCode == Constants.DYNAMIC_CLIENT_REGISTER_REQUEST_CODE) { manipulateDynamicClientResponse(result); } } /** * Manipulates the dynamic client registration response received from server. * * @param result the result of the dynamic client request */ private void manipulateDynamicClientResponse(Map<String, String> result) { String responseStatus; if (result != null) { responseStatus = result.get(Constants.STATUS); if (Constants.Status.CREATED.equals(responseStatus)) { String dynamicClientResponse = result.get(Constants.RESPONSE); if (dynamicClientResponse != null) { Preference.putString(context, getResources().getString(R.string.shared_pref_client_credentials), dynamicClientResponse); startAuthentication(); } } else if (Constants.Status.UNAUTHORIZED.equals(responseStatus)) { showAuthenticationError(); } else if (!Constants.Status.SUCCESSFUL.equals(responseStatus)) { if (result.containsKey(Constants.RESPONSE)) { showEnrollmentFailedErrorMessage( "Code: " + responseStatus + "\nError: " + result.get(Constants.RESPONSE)); } else { showEnrollmentFailedErrorMessage("Code: " + responseStatus); } } } else { showEnrollmentFailedErrorMessage(null); } } private void loadProvisioningActivity() { Intent intent = new Intent(AuthenticationActivity.this, ProvisioningActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); intent.putExtra(Constants.USERNAME, usernameVal); startActivity(intent); finish(); } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK && !isReLogin) { finish(); return true; } return super.onKeyDown(keyCode, event); } private DialogInterface.OnClickListener senderIdFailedClickListener = new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { btnSignIn.setBackgroundResource(R.drawable.btn_orange); btnSignIn.setTextColor(ContextCompat.getColor(AuthenticationActivity.this, R.color.white)); btnSignIn.setEnabled(true); } }; /** * Shows enrollment failed error. */ private void showEnrollmentFailedErrorMessage(String message) { CommonDialogUtils.stopProgressDialog(progressDialog); final String messageDescription; String descriptionText = getResources().getString(R.string.error_enrollment_failed_detail); if (message != null) { messageDescription = descriptionText + " " + message; } else { messageDescription = descriptionText; } this.runOnUiThread(new Runnable() { @Override public void run() { CommonDialogUtils.getAlertDialogWithOneButtonAndTitle(context, getResources().getString(R.string.error_enrollment_failed), messageDescription, getResources().getString(R.string.button_ok), senderIdFailedClickListener); } }); } /** * Shows internal server error message for authentication. */ private void showInternalServerErrorMessage() { CommonDialogUtils.stopProgressDialog(progressDialog); this.runOnUiThread(new Runnable() { @Override public void run() { CommonDialogUtils.getAlertDialogWithOneButtonAndTitle(context, getResources().getString(R.string.title_head_connection_error), getResources().getString(R.string.error_internal_server), getResources().getString(R.string.button_ok), null); } }); } /** * Shows credentials error message for authentication. */ private void showAuthenticationError() { CommonDialogUtils.stopProgressDialog(progressDialog); this.runOnUiThread(new Runnable() { @Override public void run() { CommonDialogUtils.getAlertDialogWithOneButtonAndTitle(context, getResources().getString(R.string.title_head_authentication_error), getResources().getString(R.string.error_authentication_failed), getResources().getString(R.string.button_ok), null); } }); } /** * Shows common error message for authentication. */ private void showAuthCommonErrorMessage() { CommonDialogUtils.stopProgressDialog(progressDialog); this.runOnUiThread(new Runnable() { @Override public void run() { CommonDialogUtils.getAlertDialogWithOneButtonAndTitle(context, getResources().getString(R.string.title_head_authentication_error), getResources().getString(R.string.error_for_all_unknown_authentication_failures), getResources().getString(R.string.button_ok), null); } }); } /** * This method is used to retrieve consumer-key and consumer-secret. */ private void getClientCredentials() { String ipSaved = Preference.getString(context.getApplicationContext(), Constants.PreferenceFlag.IP); String authenticationTitle = getResources().getString(R.string.dialog_authenticate); progressDialog = ProgressDialog.show(context, authenticationTitle, getResources().getString(R.string.dialog_message_please_wait), true); if (ipSaved != null && !ipSaved.isEmpty()) { String applicationName = Constants.API_APPLICATION_NAME_PREFIX + deviceInfo.getDeviceId(); ApiRegistrationProfile apiRegistrationProfile = new ApiRegistrationProfile(); apiRegistrationProfile.setApplicationName(applicationName); apiRegistrationProfile.setIsAllowedToAllDomains(false); apiRegistrationProfile.setIsMappingAnExistingOAuthApp(false); apiRegistrationProfile.setTags(SUBSCRIBED_API); DynamicClientManager dynamicClientManager = new DynamicClientManager(); try { dynamicClientManager.getClientCredentials(usernameVal, passwordVal, context, AuthenticationActivity.this, apiRegistrationProfile); Preference.putString(context, Constants.CLIENT_NAME, applicationName); } catch (AndroidAgentException e) { String message = "Client credentials generation failed"; Log.e(TAG, message, e); showEnrollmentFailedErrorMessage(message); } } else { String message = "There is no valid IP to contact the server"; Log.e(TAG, message); showEnrollmentFailedErrorMessage(message); } } }