Java tutorial
/* * Copyright 2014 Ericsson AB * * Licensed 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 com.etalio.android; import android.content.Context; import android.util.Base64; import com.etalio.android.client.exception.EtalioHttpError; import com.etalio.android.client.exception.EtalioProfileExpiredException; import com.etalio.android.client.models.PromotedApplications; import com.etalio.android.client.models.Status; import com.etalio.android.client.models.requests.MsisdnRequestClaim; import com.etalio.android.client.models.requests.MsisdnVerifyToken; import com.etalio.android.util.Log; import com.etalio.android.client.GsonHttpBodyConverter; import com.etalio.android.client.HttpRequest; import com.etalio.android.client.HttpResponse; import com.etalio.android.client.exception.EtalioHttpException; import com.etalio.android.client.exception.EtalioTokenException; import com.etalio.android.client.models.Action; import com.etalio.android.client.models.Application; import com.etalio.android.client.models.Country; import com.etalio.android.client.models.NewUser; import com.etalio.android.client.models.Operator; import com.etalio.android.client.models.TokenResponse; import com.etalio.android.client.models.User; import com.etalio.android.client.models.Version; import com.etalio.android.client.models.requests.CreateApplication; import com.etalio.android.client.models.requests.Msisdn; import com.etalio.android.client.models.requests.MsisdnRequestCodeResponse; import com.etalio.android.client.models.requests.MsisdnResponseCode; import com.etalio.android.client.models.requests.MsisdnResponseCodeResponse; import com.etalio.android.client.models.requests.PasswordReset; import com.etalio.android.client.models.requests.ProfileApplicationAdd; import org.apache.http.client.HttpClient; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.nio.charset.Charset; import java.util.HashMap; import java.util.Map; public class EtalioExtendedAPI extends EtalioAPI { private static final String TAG = EtalioExtendedAPI.class.getCanonicalName(); private static final String PARAM_USERNAME = "username"; private static final String PARAM_PASSWORD = "password"; protected static final String PROFILE_APP = "profileApp"; protected static final String PROFILE_REMOVE_APP = "profileRemoveApp"; protected static final String PASSWORD_RESET = "passwordReset"; protected static final String PROFILE_SMS = "profileSms"; protected static final String FEATURED_APPLICATIONS = "featured-applications"; protected static final String COUNTRIES = "countries"; protected static final String OPERATORS = "operators"; protected static final String VERSION = "version"; protected static final String MSISDN = "msisdn"; protected static final String MYAPPS = "myapps"; protected static final String ACTIONS = "actions"; protected static final String APPLICATIONS = "applications"; protected static final String PROFILES = "profiles"; protected static final String CLAIM_MSISDN = "claim-msisdn"; protected static final String PROMOTED_APPS = "promoted-apps"; private final String baseUrl; public EtalioExtendedAPI(Context context, String clientID, String clientSecret) { this(context, clientID, clientSecret, API_URL, API_VERSION); } public EtalioExtendedAPI(Context context, String clientID, String clientSecret, String apiUrl, String apiVersion) { super(context, clientID, clientSecret, apiUrl, apiVersion); Log.e(TAG, "Creating extended API"); baseUrl = apiUrl + apiVersion; domainMap.put(PROFILE_APP, baseUrl + "/profile/me/applications"); domainMap.put(PROFILE_REMOVE_APP, baseUrl + "/profile/me/application"); domainMap.put(PASSWORD_RESET, baseUrl + "/profile/password-reset"); domainMap.put(PROFILE_SMS, baseUrl + "/profile/me/sms"); domainMap.put(FEATURED_APPLICATIONS, baseUrl + "/applications?featured=true"); domainMap.put(COUNTRIES, baseUrl + "/countries"); domainMap.put(OPERATORS, baseUrl + "/netops"); domainMap.put(VERSION, baseUrl + "/version"); domainMap.put(MSISDN, baseUrl + "/msisdn"); domainMap.put(MYAPPS, baseUrl + "/profile/me/applications"); domainMap.put(ACTIONS, baseUrl + "/profile/me/notifications"); domainMap.put(APPLICATIONS, baseUrl + "/applications"); domainMap.put(PROFILES, baseUrl + "/profiles"); domainMap.put(CLAIM_MSISDN, baseUrl + "/msisdn/claim"); domainMap.put(PROMOTED_APPS, baseUrl + "/applications/promoted"); } /** * Send a MT SMS to the device from the server with a request code. * @param phoneNumber * @return * @throws EtalioTokenException * @throws IOException * @throws EtalioHttpException */ public Status sendRequestCode(String phoneNumber) throws EtalioTokenException, IOException, EtalioHttpException { Msisdn msisdn = new Msisdn(phoneNumber, true, null); return apiCall(MSISDN, HttpRequest.HttpMethod.POST, msisdn, Status.class); } /** * Verify if request code is correct. * @param phoneNumber * @param requestCode * @throws EtalioTokenException * @throws IOException * @throws EtalioHttpException */ public void verifyRequestCode(String phoneNumber, String requestCode) throws EtalioTokenException, IOException, EtalioHttpException { MsisdnVerifyToken msisdn = new MsisdnVerifyToken(phoneNumber, requestCode); MsisdnRequestCodeResponse response = apiCall(MSISDN, HttpRequest.HttpMethod.POST, msisdn, MsisdnRequestCodeResponse.class); } /** * Get a MO SMS response code to be sent from device to server. * @param phoneNumber * @return * @throws EtalioTokenException * @throws IOException * @throws EtalioHttpException */ public String getResponseCode(String phoneNumber) throws EtalioTokenException, IOException, EtalioHttpException { MsisdnResponseCode msisdn = new MsisdnResponseCode(phoneNumber, true); return apiCall(MSISDN, HttpRequest.HttpMethod.POST, msisdn, MsisdnResponseCodeResponse.class) .getResponseCode(); } public User createProfile(final String name, final String msisdn, final String requestCode, final String responseCode, final String password, String email, Boolean acceptsEula) throws IOException, EtalioTokenException, EtalioHttpException { NewUser newUser = new NewUser(name, msisdn, requestCode, responseCode, password, email, acceptsEula); return apiCall(PROFILES, HttpRequest.HttpMethod.POST, newUser, User.class); } /** * Sign in as application and not as a user. Only available for trusted apps. * @return * @throws EtalioTokenException * @throws IOException * @throws EtalioHttpException */ public boolean requestApplicationSignIn() throws EtalioTokenException, IOException, EtalioHttpException { byte[] body = buildApplicationAuthenticationRequestBody(); boolean result; try { result = privateSignIn(body); } catch (EtalioHttpException e) { if (e.getResponseCode() == 401) return false; throw e; } return result; } /** * Sign in a user with grant-type password. * @param msisdn * @param password * @return * @throws IOException * @throws EtalioTokenException * @throws EtalioHttpException */ public boolean requestPrivateSignIn(String msisdn, String password) throws IOException, EtalioTokenException, EtalioHttpException, EtalioProfileExpiredException { byte[] body = buildAuthenticationRequestBody(msisdn, password); boolean result; try { result = privateSignIn(body); } catch (EtalioHttpException e) { if (e.getErrorType() == EtalioHttpError.PROFILE_EXPIRED) { throw new EtalioProfileExpiredException(); } if (e.getResponseCode() == 401) return false; throw e; } return result; } private boolean privateSignIn(byte[] body) throws IOException, EtalioHttpException, EtalioTokenException { Log.v(SDK_TAG, "privateSignIn"); Map<String, String> headers = new HashMap<String, String>(); addEtalioUserAgent(headers); String authenticationString = mClientId + ":" + mClientSecret; String authenticationString64 = Base64.encodeToString(authenticationString.getBytes(), Base64.NO_WRAP); headers.put("Authorization", "Basic " + authenticationString64); Log.v(TAG, "privateSignIn:: POST " + authenticationString + " " + getUrl("token", null) + " " + new String(body, "UTF-8")); HttpRequest request = new HttpRequest(HttpRequest.HttpMethod.POST, getUrl("token", null), headers, body, CONTENT_TYPE_APPLICATION_X_WWW_FORM_URLENCODED, body.length); HttpResponse<TokenResponse> response = null; response = getHttpClient().executeRequest(request, new GsonHttpBodyConverter<TokenResponse>(), TokenResponse.class); Log.v(TAG, "privateSignIn::" + response.getStatus() + " : " + new String(getHttpBodyConverter().toBody(response.getBody(), "UTF-8"), "UTF-8")); updateEtalioToken(response); return true; } public boolean removeAccount() throws EtalioTokenException, IOException, EtalioHttpException { apiCall("myprofile", HttpRequest.HttpMethod.DELETE, null, Object.class); return true; } private byte[] buildApplicationAuthenticationRequestBody() { Map<String, String> params = new HashMap<String, String>(); params.put(PARAM_GRANT_TYPE, "client_credentials"); params.put(PARAM_USERNAME, mClientId); params.put(PARAM_PASSWORD, mClientSecret); return generateFormEncodedRequestBody(params); } private byte[] buildAuthenticationRequestBody(String username, String password) { Map<String, String> params = new HashMap<String, String>(); params.put(PARAM_GRANT_TYPE, "password"); try { params.put(PARAM_USERNAME, URLEncoder.encode(username, "UTF-8")); params.put(PARAM_PASSWORD, URLEncoder.encode(password, "UTF-8")); } catch (UnsupportedEncodingException e) { return null; } return generateFormEncodedRequestBody(params); } public Application createApplication(CreateApplication createApplication) throws EtalioTokenException, IOException, EtalioHttpException { return apiCall("applications", HttpRequest.HttpMethod.POST, createApplication, Application.class); } public TokenResponse addApplication(String clientId, String packageName) throws EtalioTokenException, IOException, EtalioHttpException { ProfileApplicationAdd profileApplicationAdd = new ProfileApplicationAdd(clientId, "profile.r", packageName); return apiCall(PROFILE_APP, HttpRequest.HttpMethod.POST, profileApplicationAdd, TokenResponse.class); } public boolean revokeAccess(String applicationId) throws EtalioTokenException, IOException, EtalioHttpException { String encodedId = URLEncoder.encode(applicationId, "UTF-8"); String domain = addToDomainMap("profileRemoveApp-" + encodedId, domainMap.get(PROFILE_REMOVE_APP) + "/" + encodedId); try { apiCall(domain, HttpRequest.HttpMethod.DELETE, null, Object.class); } catch (EtalioHttpException e) { if (e.getResponseCode() == 404) return false; throw e; } return true; } public boolean resetPassword(String msisdn) throws EtalioTokenException, IOException, EtalioHttpException { PasswordReset passwordReset = new PasswordReset(msisdn); apiCall(PASSWORD_RESET, HttpRequest.HttpMethod.POST, passwordReset, Object.class); return true; } public boolean checkPhoneNumberExists(Msisdn msisdn) throws EtalioTokenException, IOException, EtalioHttpException { try { apiCall(MSISDN, HttpRequest.HttpMethod.POST, msisdn, Object.class); } catch (EtalioHttpException e) { if (e.getResponseCode() == 404) return false; throw e; } return true; } public Application[] getFeaturedApplications() throws EtalioTokenException, IOException, EtalioHttpException { return apiCall(FEATURED_APPLICATIONS, HttpRequest.HttpMethod.GET, null, Application[].class); } /** * Gets the operators in Etalio * * Use get @link{#getOperators(String) getOperators} instead. * @return all the operators in etalio * * @throws EtalioTokenException * @throws IOException * @throws EtalioHttpException */ @Deprecated public Operator[] getOperators() throws EtalioTokenException, IOException, EtalioHttpException { return apiCall(OPERATORS, HttpRequest.HttpMethod.GET, null, Operator[].class); } /** * Get the operators for a given msisdn * * @param msisdn the phone number * @return the operators in the country for the MSISDN * @throws EtalioTokenException * @throws IOException * @throws EtalioHttpException */ public Operator[] getOperators(String msisdn) throws EtalioTokenException, IOException, EtalioHttpException { String requestIdentifier = String.format("netops-%s", msisdn); String requestUrl = String.format("%s/netops?msisdn=%s", baseUrl, URLEncoder.encode(msisdn, "UTF-8")); domainMap.put(requestIdentifier, requestUrl); return apiCall(requestIdentifier, HttpRequest.HttpMethod.GET, null, Operator[].class); } public Country[] getCountries() throws EtalioTokenException, IOException, EtalioHttpException { return apiCall(COUNTRIES, HttpRequest.HttpMethod.GET, null, Country[].class, false); } public Version[] getVersions() throws EtalioTokenException, IOException, EtalioHttpException { return apiCall(VERSION, HttpRequest.HttpMethod.GET, null, Version[].class); } public Version getAndroidVersion() throws EtalioTokenException, IOException, EtalioHttpException { Version[] versions = getVersions(); for (int i = 0; i < versions.length; i++) { if ("android".equals(versions[i].getPlatform())) { return versions[i]; } } return null; } /** * Get list of granted of applications for the currently logged in User. * @return List of applications that the user granted access. * @throws IOException * @throws EtalioTokenException * @throws EtalioHttpException */ public Application[] getMyGrantedApplications() throws IOException, EtalioTokenException, EtalioHttpException { return apiCall(MYAPPS, HttpRequest.HttpMethod.GET, null, Application[].class); } /** * Gets the list of operator promoted applications * @param operatorId the operator id * @return Array of operator promoted applications * @throws EtalioTokenException * @throws IOException * @throws EtalioHttpException */ public Application[] getOperatorPromotedApplications(String operatorId) throws EtalioTokenException, IOException, EtalioHttpException { String requestIdentifier = String.format("operator-apps-%s", operatorId); String requestUrl = String.format("%s/applications?operator=%s", new Object[] { baseUrl, URLEncoder.encode(operatorId, "UTF8") }); domainMap.put(requestIdentifier, requestUrl); return apiCall(requestIdentifier, HttpRequest.HttpMethod.GET, null, Application[].class); } /** * Gets the list of promoted applications * @return the applications * @throws EtalioTokenException * @throws IOException * @throws EtalioHttpException */ public PromotedApplications getPromotedApplications() throws EtalioTokenException, IOException, EtalioHttpException { return apiCall(PROMOTED_APPS, HttpRequest.HttpMethod.GET, null, PromotedApplications.class); } /** * Get list of actions for the currently logged in User. * @return List of actions. * @throws IOException * @throws EtalioTokenException * @throws EtalioHttpException */ public Action[] getMyActions() throws EtalioTokenException, IOException, EtalioHttpException { return apiCall(ACTIONS, HttpRequest.HttpMethod.GET, null, com.etalio.android.client.models.Action[].class); } /** * Claims a msisdn * @param msisdn the msisdn to claim * @param requestCode the request code to verify the number with. The request code is probably sent over SMS * @return * @throws EtalioTokenException * @throws IOException * @throws EtalioHttpException */ public boolean requestClaimMsisdn(String msisdn, String requestCode) throws EtalioTokenException, IOException, EtalioHttpException { final String OK = "OK"; MsisdnRequestClaim request = new MsisdnRequestClaim(msisdn, requestCode); Status s = apiCall(CLAIM_MSISDN, HttpRequest.HttpMethod.POST, request, Status.class); if (s != null) { return OK.equals(s.getStatus()); } return false; } }