diff --git a/build.gradle b/build.gradle index 9bf5a8c..a7f57f4 100644 --- a/build.gradle +++ b/build.gradle @@ -32,13 +32,16 @@ dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile 'com.android.support:appcompat-v7:23.1.1' compile 'com.squareup.okhttp:okhttp:2.0.0' - compile 'com.squareup.retrofit:retrofit:1.9.0' + compile 'com.squareup.retrofit2:retrofit:2.1.0' compile 'com.google.code.gson:gson:2.4' - compile 'com.google.android.gms:play-services-gcm:8.4.0' + compile 'com.google.firebase:firebase-messaging:9.8.0' + compile 'com.google.android.gms:play-services:9.8.0' compile 'com.github.fge:json-patch:1.9' compile 'com.snappydb:snappydb-lib:0.5.0' compile 'com.esotericsoftware.kryo:kryo:2.24.0' compile 'com.github.nkzawa:socket.io-client:0.5.0' + compile 'com.squareup.retrofit2:converter-gson:2.1.0' + compile 'com.squareup.okhttp3:logging-interceptor:3.3.1' } if(file("..//upload_archives_task.gradle").exists()) { @@ -52,3 +55,4 @@ if(file("..//upload_archives_task.gradle").exists()) { apply plugin: 'signing' apply from: "..//upload_archives_task.gradle" } + diff --git a/src/main/java/io/telepat/sdk/Telepat.java b/src/main/java/io/telepat/sdk/Telepat.java index c5ae030..3f7ab0f 100644 --- a/src/main/java/io/telepat/sdk/Telepat.java +++ b/src/main/java/io/telepat/sdk/Telepat.java @@ -2,12 +2,12 @@ import android.content.Context; +import com.google.android.gms.common.ConnectionResult; +import com.google.android.gms.common.GoogleApiAvailability; +import com.google.android.gms.common.GooglePlayServicesNotAvailableException; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.HashMap; @@ -15,12 +15,12 @@ import java.util.Map; import java.util.concurrent.CopyOnWriteArrayList; -import io.telepat.BuildConfig; import io.telepat.sdk.data.TelepatInternalDB; import io.telepat.sdk.data.TelepatSnappyDb; import io.telepat.sdk.models.Channel; import io.telepat.sdk.models.ContextUpdateListener; import io.telepat.sdk.models.OnChannelEventListener; +import io.telepat.sdk.models.TelepatCallback; import io.telepat.sdk.models.TelepatContext; import io.telepat.sdk.models.TelepatProxyRequest; import io.telepat.sdk.models.TelepatProxyResponse; @@ -34,673 +34,711 @@ import io.telepat.sdk.networking.requests.RegisterDeviceRequest; import io.telepat.sdk.networking.requests.RegisterFacebookUserRequest; import io.telepat.sdk.networking.requests.RegisterTwitterUserRequest; +import io.telepat.sdk.networking.responses.ApiError; import io.telepat.sdk.networking.responses.ContextsApiResponse; import io.telepat.sdk.networking.responses.GenericApiResponse; import io.telepat.sdk.networking.responses.TelepatCountCallback; -import io.telepat.sdk.networking.transports.gcm.GcmRegistrar; import io.telepat.sdk.utilities.TelepatConstants; import io.telepat.sdk.utilities.TelepatLogger; -import retrofit.Callback; -import retrofit.RestAdapter; -import retrofit.RetrofitError; -import retrofit.android.AndroidLog; -import retrofit.client.Response; +import okhttp3.OkHttpClient; +import okhttp3.logging.HttpLoggingInterceptor; +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Response; +import retrofit2.Retrofit; +import retrofit2.converter.gson.GsonConverterFactory; /** * Created by Andrei Marinescu, catalinivan on 10/03/15. - * + *

* Telepat Main Orchestrator */ -public final class Telepat -{ - /** - * Telepat singleton instance - */ - private static Telepat mInstance; - /** - * Reference to the application context - */ - private Context mContext; - /** - * References to the currently available Telepat contexts - */ - private HashMap mServerContexts; - /** - * Reference to a Telepat Sync API client - */ - private OctopusApi apiClient; - /** - * Retrofit RequestInterceptor implementation for injecting the proper authentication headers - */ - private OctopusRequestInterceptor requestInterceptor; - /** - * Internal storage reference - */ - private TelepatInternalDB internalDB; - /** - * Locally registered Channel instances - */ - private HashMap subscriptions = new HashMap<>(); - /** - * Context update listener array - */ - private CopyOnWriteArrayList contextUpdateListeners = new CopyOnWriteArrayList<>(); - /** - * Unique device identifier - */ - private String localUdid; - - /** - * Configured Telepat Application ID - */ - private String appId; - - private Telepat() { } - - /** - * - * @return Returns a reference to the singleton instance - */ - public static Telepat getInstance() - { - if (mInstance == null) { - mInstance = new Telepat(); - } - - return mInstance; - } - - /** - * Get access to an instance controlling the internal storage DB - * @return An instance of a class implementing TelepatInternalDB - */ - public TelepatInternalDB getDBInstance() { - return internalDB; - } +public final class Telepat { + + public static boolean isDebugMode = false; + + /** + * Telepat singleton instance + */ + private static Telepat mInstance; + /** + * Reference to the application context + */ + private Context mContext; + /** + * References to the currently available Telepat contexts + */ + private HashMap mServerContexts; + /** + * Reference to a Telepat Sync API client + */ + private OctopusApi apiClient; + /** + * Retrofit RequestInterceptor implementation for injecting the proper authentication headers + */ + private OctopusRequestInterceptor requestInterceptor; + /** + * Internal storage reference + */ + private TelepatInternalDB internalDB; + /** + * Locally registered Channel instances + */ + private HashMap subscriptions = new HashMap<>(); + /** + * Context update listener array + */ + private CopyOnWriteArrayList contextUpdateListeners = new CopyOnWriteArrayList<>(); + /** + * Unique device identifier + */ + private String localUdid; + + /** + * Configured Telepat Application ID + */ + private String appId; + public Retrofit retrofit; + + private Telepat() { + } + + /** + * @return Returns a reference to the singleton instance + */ + public static Telepat getInstance() { + if (mInstance == null) { + mInstance = new Telepat(); + } + + return mInstance; + } + + /** + * Get access to an instance controlling the internal storage DB + * + * @return An instance of a class implementing TelepatInternalDB + */ + public TelepatInternalDB getDBInstance() { + return internalDB; + } /** * Get access to an Retrofit instance that is able to communicate with the Telepat Sync API + * * @return An OctopusApi instance */ - public OctopusApi getAPIInstance() { return apiClient; } - - @SuppressWarnings("unused") - public void emptyDB(Context ctx) { - if(internalDB == null) { - internalDB = new TelepatSnappyDb(ctx); - } - internalDB.empty(); - } - - public void initialize(Context context, - final String telepatEndpoint, - final String clientApiKey, - final String clientAppId, - String senderId) { - mContext = context.getApplicationContext(); - internalDB = new TelepatSnappyDb(context); - appId = clientAppId; - TelepatConstants.GCM_SENDER_ID = senderId; - initHTTPClient(telepatEndpoint, clientApiKey, clientAppId); - new GcmRegistrar(mContext).initGcmRegistration(); - - String JWTtoken = (String) internalDB.getOperationsData(TelepatConstants.JWT_KEY, null, String.class); - if(JWTtoken != null) { - requestInterceptor.setAuthorizationToken(JWTtoken); - refreshToken(null); - } - - requestContexts(); -// String registrationId = (String) Telepat.getInstance() -// .getDBInstance() -// .getOperationsData(GcmRegistrar.PROPERTY_REG_ID, "", String.class); - TelepatLogger.log("Initialized Telepat Android SDK version " + BuildConfig.VERSION_NAME); - } + public OctopusApi getAPIInstance() { + return apiClient; + } + @SuppressWarnings("unused") + public void emptyDB(Context ctx) { + if (internalDB == null) { + internalDB = new TelepatSnappyDb(ctx); + } + internalDB.empty(); + } + + public void initialize(Context context, + final String telepatEndpoint, + final String clientApiKey, + final String clientAppId, + String senderId) { + + try { + if (isGooglePlayServicesAvailable(context)) { + mContext = context.getApplicationContext(); + internalDB = new TelepatSnappyDb(context); + appId = clientAppId; + TelepatConstants.GCM_SENDER_ID = senderId; + initHTTPClient(telepatEndpoint, clientApiKey, clientAppId); + // new GcmRegistrar(mContext).initGcmRegistration(); + + String JWTtoken = (String) internalDB.getOperationsData(TelepatConstants.JWT_KEY, null, String.class); + if (JWTtoken != null) { + requestInterceptor.setAuthorizationToken(JWTtoken); + refreshToken(null); + } + + requestContexts(); + // String registrationId = (String) Telepat.getInstance() + // .getDBInstance() + // .getOperationsData(GcmRegistrar.PROPERTY_REG_ID, "", String.class); + // TelepatLogger.log("Initialized Telepat Android SDK version " + BuildConfig.VERSION_NAME); + } + } catch (GooglePlayServicesNotAvailableException e) { + e.printStackTrace(); + } + } + + + public boolean isGooglePlayServicesAvailable(Context context) throws GooglePlayServicesNotAvailableException { + GoogleApiAvailability googleApiAvailability = GoogleApiAvailability.getInstance(); + int status = googleApiAvailability.isGooglePlayServicesAvailable(context); + if (status != ConnectionResult.SUCCESS) { + throw new GooglePlayServicesNotAvailableException(status); + } + return true; + } /** * Close the current Telepat instance. You should reinitialize the Telepat SDK before doing * additional work. */ - @SuppressWarnings("unused") - public void destroy() { - internalDB.close(); - } + @SuppressWarnings("unused") + public void destroy() { + internalDB.close(); + } /** * Configures the OctopusApi instance with relevant credentials + * * @param clientApiKey A string containing a Telepat client API key - * @param clientAppId A string containing the corresponding Telepat application ID + * @param clientAppId A string containing the corresponding Telepat application ID */ - private void initHTTPClient(String telepatEndpoint, String clientApiKey, final String clientAppId) { - requestInterceptor = new OctopusRequestInterceptor(clientApiKey, clientAppId); + private void initHTTPClient(String telepatEndpoint, String clientApiKey, final String clientAppId) { + requestInterceptor = new OctopusRequestInterceptor(clientApiKey, clientAppId); - RestAdapter.Builder rBuilder = new RestAdapter.Builder() - .setEndpoint(telepatEndpoint) - .setRequestInterceptor(requestInterceptor); - if(TelepatConstants.RETROFIT_DEBUG_ENABLED) - rBuilder.setLogLevel(RestAdapter.LogLevel.FULL) - .setLog(new AndroidLog(TelepatConstants.TAG)); + HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(); + loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY); - RestAdapter restAdapter = rBuilder.build(); - apiClient = restAdapter.create(OctopusApi.class); - } + OkHttpClient.Builder okHttpClient = new OkHttpClient.Builder(); + okHttpClient.interceptors().add(requestInterceptor); + okHttpClient.interceptors().add(loggingInterceptor); + + retrofit = new Retrofit.Builder() + .client(okHttpClient.build()) + .addConverterFactory(GsonConverterFactory.create()) + .baseUrl(telepatEndpoint).build(); + apiClient = retrofit.create(OctopusApi.class); + } /** * Send the Telepat Sync API a device registration request - * @param regId A GCM token for the current device + * + * @param regId A GCM token for the current device * @param shouldUpdateBackend If true, an update should be sent to the Telepat cloud instance * regardless of the state of the token (new/already sent) */ - public void registerDevice(String regId, boolean shouldUpdateBackend) - { - String udid = (String) internalDB.getOperationsData(TelepatConstants.UDID_KEY, - "", - String.class); - if(!udid.isEmpty()) { - for (ContextUpdateListener listener : Telepat.this.contextUpdateListeners) { - listener.deviceRegisterSuccess(); - } - return; - } - - if(udid.isEmpty() || shouldUpdateBackend) { - RegisterDeviceRequest request = new RegisterDeviceRequest(regId); - apiClient.registerDevice(request.getParams(), new Callback() { - @Override - public void success(GenericApiResponse octopusResponse, - retrofit.client.Response response) { - TelepatLogger.log("Register device success"); - if (octopusResponse.status == 200 && octopusResponse.content.get("identifier") != null) { - requestInterceptor.setUdid((String)octopusResponse.content.get("identifier")); - internalDB.setOperationsData(TelepatConstants.UDID_KEY, - octopusResponse.content.get("identifier")); - for (ContextUpdateListener listener : Telepat.this.contextUpdateListeners) { - listener.deviceRegisterSuccess(); - } - TelepatLogger.log("Received Telepat UDID: " + octopusResponse.content.get("identifier")); - } - } - - @Override - public void failure(RetrofitError error) { - TelepatLogger.log("Register device failure."); - - } - }); - } //else { - //TODO send update - //} - } + public void registerDevice(final String regId, boolean shouldUpdateBackend) { + String udid = (String) internalDB.getOperationsData(TelepatConstants.UDID_KEY, + "", + String.class); + if (!udid.isEmpty()) { + for (ContextUpdateListener listener : Telepat.this.contextUpdateListeners) { + listener.deviceRegisterSuccess(); + } + return; + } + + if (udid.isEmpty() || shouldUpdateBackend) { + RegisterDeviceRequest request = new RegisterDeviceRequest(regId); + Call call = apiClient.registerDevice(request.getParams()); + call.enqueue(new TelepatCallback() { + @Override + public void success(GenericApiResponse apiResponse) { + TelepatLogger.log("Register device success"); + if (apiResponse.status == 200 && apiResponse.getContent().get("identifier") != null) { + requestInterceptor.setUdid((String) apiResponse.getContent().get("identifier")); + internalDB.setOperationsData(TelepatConstants.UDID_KEY, + apiResponse.getContent().get("identifier")); + for (ContextUpdateListener listener : Telepat.this.contextUpdateListeners) { + listener.deviceRegisterSuccess(); + } + TelepatLogger.log("Received Telepat UDID: " + apiResponse.getContent().get("identifier")); + } + } + + @Override + public void failure(ApiError error) { + TelepatLogger.log("Register device failure. " + error.message()); + } + + }); + } //else { + //TODO send update + //} + } /** * Retrieve the currently active contexts for the current Telepat application */ - private void requestContexts() - { - apiClient.updateContexts(new Callback() { - @Override - public void success(ContextsApiResponse contextMap, - retrofit.client.Response response) { - updateContexts(contextMap); - } - - @Override - public void failure(RetrofitError error) { - //TODO: bubble errors to the User level - if (error != null && error.getResponse() != null) { - if (error.getResponse().getStatus() == 404) { - apiClient.updateContextsCompat(new Callback() { - @Override - public void success(ContextsApiResponse contextsApiResponse, Response response) { - updateContexts(contextsApiResponse); - } - - @Override - public void failure(RetrofitError error) { - TelepatLogger.log("Failed to get contexts" + error.getMessage()); - } - }); - } else { - TelepatLogger.log("Failed to get contexts" + error.getMessage()); - } - } else { - TelepatLogger.log("Failed to get contexts"); - } - } - }); - } - - private void updateContexts(ContextsApiResponse contextMap) { - if (contextMap == null) return; - if (mServerContexts == null) mServerContexts = new HashMap<>(); - for (TelepatContext ctx : contextMap.content) - mServerContexts.put(ctx.getId(), ctx); - for (ContextUpdateListener listener : Telepat.this.contextUpdateListeners) { - listener.contextInitializeSuccess(); - } - TelepatLogger.log("Retrieved " + contextMap.content.size() + " contexts"); - } - - /** - * Send a Telepat Sync API call for registering a user with the Facebook auth provider - * @param fbToken A Facebook OAUTH token - */ - @Deprecated - @SuppressWarnings("unused") - public void register(final String fbToken, final TelepatRequestListener loginListener) { - registerFacebookUser(fbToken, loginListener); - } - - /** - * Send a Telepat Sync API call for registering a user with the Facebook auth provider - * @param fbToken A Facebook OAUTH token - */ - @SuppressWarnings("unused") - public void registerFacebookUser(final String fbToken, final TelepatRequestListener loginListener) - { - internalDB.setOperationsData(TelepatConstants.FB_TOKEN_KEY, fbToken); - apiClient.registerUserFacebook(new RegisterFacebookUserRequest(fbToken).getParams(), new Callback>() { - @Override - public void success(Map userRegisterResponse, retrofit.client.Response response) { - apiClient.loginFacebook( - new RegisterFacebookUserRequest(fbToken).getParams(), - new UserLoginCallback(requestInterceptor, internalDB, loginListener) - ); - - } - - @Override - public void failure(RetrofitError error) { - if (error.getResponse().getStatus() == 409) { - apiClient.loginFacebook( - new RegisterFacebookUserRequest(fbToken).getParams(), - new UserLoginCallback(requestInterceptor, internalDB, loginListener) - ); - } else { - TelepatLogger.error("user register failed"); - loginListener.onError(error); - } - } - }); - } - - /** - * Send a Telepat Sync API call for registering a user with the Twitter auth provider - */ - @SuppressWarnings("unused") - public void registerTwitterUser(final String oauthToken, final String oauthTokenSecret, final TelepatRequestListener loginListener) - { - internalDB.setOperationsData(TelepatConstants.TWITTER_TOKEN_KEY, oauthToken); - internalDB.setOperationsData(TelepatConstants.TWITTER_SECRET_TOKEN_KEY, oauthTokenSecret); - apiClient.registerUserTwitter(new RegisterTwitterUserRequest(oauthToken, oauthTokenSecret).getParams(), new Callback>() { - @Override - public void success(Map userRegisterResponse, retrofit.client.Response response) { - TelepatLogger.log("User registered"); - apiClient.loginTwitter( - new RegisterTwitterUserRequest(oauthToken, oauthTokenSecret).getParams(), - new UserLoginCallback(requestInterceptor, internalDB, loginListener) - ); - } - - @Override - public void failure(RetrofitError error) { - if (error.getResponse().getStatus() == 409) { - apiClient.loginTwitter( - new RegisterTwitterUserRequest(oauthToken, oauthTokenSecret).getParams(), - new UserLoginCallback(requestInterceptor, internalDB, loginListener) - ); - } else { - TelepatLogger.error("User register failed"); - } - } - }); - } - - /** - * Submit a set of user credentials for registering a new user with the Email/Password auth provider - * @param email The username of the Telepat user - * @param password A cleartext password to be associated - * @param name The displayable name of the user - * @param callbackUrl An optional deep link for redirecting the user back into the app after confirming his email address - * @param listener A callback for success and error events - */ - @SuppressWarnings("unused") - public void createUser(final String email, final String password, final String name, final String callbackUrl, final HashMap additionalMetadata, final UserCreateListener listener) { - if(email!=null && password!=null && name!=null) { - HashMap userHash = new HashMap<>(); - userHash.put("username", email); - userHash.put("email", email); - userHash.put("password", password); - userHash.put("name", name); - - if(additionalMetadata != null) { - userHash.putAll(additionalMetadata); - } - - if(callbackUrl != null && !callbackUrl.isEmpty()) { - userHash.put("callbackUrl", callbackUrl); - } - - apiClient.registerUserEmailPass(userHash, new Callback>() { - @Override - public void success(Map stringStringMap, Response response) { - listener.onUserCreateSuccess(); - } - - @Override - public void failure(RetrofitError error) { - listener.onUserCreateFailure(error); - } - }); - } - } - - @SuppressWarnings("unused") - public void createUser(final String email, final String password, final String name, final HashMap additionalMetadata, final UserCreateListener listener) { - createUser(email, password, name, null, additionalMetadata, listener); -} + private void requestContexts() { + final Call callUpdateContexts = apiClient.updateContexts(); + callUpdateContexts.enqueue(new Callback() { + @Override + public void onResponse(Call call, Response response) { + if (response.body().status == 200) { + updateContexts(response.body()); + } else if (response.body().status == 404) { + Call callcallUpdateContextsCompat = apiClient.updateContextsCompat(); + callcallUpdateContextsCompat.enqueue(new Callback() { + @Override + public void onResponse(Call call, Response response) { + updateContexts(response.body()); + } + + @Override + public void onFailure(Call call, Throwable t) { + TelepatLogger.log("Failed to get contexts" + t.getMessage()); + } + }); + } else { + TelepatLogger.log("Failed to get contexts"); + } + } + + @Override + public void onFailure(Call call, Throwable t) { + TelepatLogger.log("Failed to get contexts"); + t.printStackTrace(); + } + }); + } + + private void updateContexts(ContextsApiResponse contextMap) { + if (contextMap == null) return; + if (mServerContexts == null) mServerContexts = new HashMap<>(); + for (TelepatContext ctx : contextMap.content) + mServerContexts.put(ctx.getId(), ctx); + for (ContextUpdateListener listener : Telepat.this.contextUpdateListeners) { + listener.contextInitializeSuccess(); + } + TelepatLogger.log("Retrieved " + contextMap.content.size() + " contexts"); + } + + /** + * Send a Telepat Sync API call for registering a user with the Facebook auth provider + * + * @param fbToken A Facebook OAUTH token + */ + @Deprecated + @SuppressWarnings("unused") + public void register(final String fbToken, final TelepatRequestListener loginListener) { + registerFacebookUser(fbToken, loginListener); + } + + /** + * Send a Telepat Sync API call for registering a user with the Facebook auth provider + * + * @param fbToken A Facebook OAUTH token + */ + @SuppressWarnings("unused") + public void registerFacebookUser(final String fbToken, final TelepatRequestListener loginListener) { + internalDB.setOperationsData(TelepatConstants.FB_TOKEN_KEY, fbToken); + + Call registerUserFacebookCall = apiClient.registerUserFacebook(new RegisterFacebookUserRequest(fbToken).getParams()); + + registerUserFacebookCall.enqueue(new Callback() { + @Override + public void onResponse(Call call, Response response) { + Call loginFacebookCall = apiClient.loginFacebook(new RegisterFacebookUserRequest(fbToken).getParams()); + if (response.isSuccessful()) { + loginFacebookCall.enqueue(new UserLoginCallback(requestInterceptor, internalDB, loginListener)); + } else { + ApiError apiError = ApiError.parseError(response); + if (apiError.status() == 409) { + loginFacebookCall.enqueue(new UserLoginCallback(requestInterceptor, internalDB, loginListener)); + } else { + + TelepatLogger.error("user register failed"); + loginListener.onError(apiError); + } + } + } + + @Override + public void onFailure(Call call, Throwable t) { + TelepatLogger.error(t.getMessage()); + } + }); + } + + /** + * Send a Telepat Sync API call for registering a user with the Twitter auth provider + */ + @SuppressWarnings("unused") + public void registerTwitterUser(final String oauthToken, final String oauthTokenSecret, final TelepatRequestListener loginListener) { + internalDB.setOperationsData(TelepatConstants.TWITTER_TOKEN_KEY, oauthToken); + internalDB.setOperationsData(TelepatConstants.TWITTER_SECRET_TOKEN_KEY, oauthTokenSecret); + + Call registerUserTwitterCall = apiClient.registerUserTwitter(new RegisterTwitterUserRequest(oauthToken, oauthTokenSecret).getParams()); + registerUserTwitterCall.enqueue(new Callback() { + @Override + public void onResponse(Call call, Response response) { + Call loginTwitterCall = apiClient.loginTwitter(new RegisterTwitterUserRequest(oauthToken, oauthTokenSecret).getParams()); + if (response.isSuccessful()) { + TelepatLogger.log("User registered"); + loginTwitterCall.enqueue(new UserLoginCallback(requestInterceptor, internalDB, loginListener)); + } else { + ApiError apiError = ApiError.parseError(response); + if (apiError.status() == 409) { + loginTwitterCall.enqueue(new UserLoginCallback(requestInterceptor, internalDB, loginListener)); + } else { + TelepatLogger.error("User register failed"); + } + } + } + + @Override + public void onFailure(Call call, Throwable t) { + TelepatLogger.error(t.getMessage()); + t.printStackTrace(); + } + }); + } + + /** + * Submit a set of user credentials for registering a new user with the Email/Password auth provider + * + * @param email The username of the Telepat user + * @param password A cleartext password to be associated + * @param name The displayable name of the user + * @param callbackUrl An optional deep link for redirecting the user back into the app after confirming his email address + * @param listener A callback for success and error events + */ + @SuppressWarnings("unused") + public void createUser(final String email, final String password, final String name, final String callbackUrl, final HashMap additionalMetadata, final UserCreateListener listener) { + if (email != null && password != null && name != null) { + HashMap userHash = new HashMap<>(); + userHash.put("username", email); + userHash.put("email", email); + userHash.put("password", password); + userHash.put("name", name); + + if (additionalMetadata != null) { + userHash.putAll(additionalMetadata); + } + + if (callbackUrl != null && !callbackUrl.isEmpty()) { + userHash.put("callbackUrl", callbackUrl); + } + + Call registerUserEmailPassCall = apiClient.registerUserEmailPass(userHash); + registerUserEmailPassCall.enqueue(new TelepatCallback() { + + @Override + public void success(GenericApiResponse apiResponse) { + listener.onUserCreateSuccess(); + } + + @Override + public void failure(ApiError error) { + listener.onUserCreateFailure(error); + } + + }); + + } + } + + @SuppressWarnings("unused") + public void createUser(final String email, final String password, final String name, final HashMap additionalMetadata, final UserCreateListener listener) { + createUser(email, password, name, null, additionalMetadata, listener); + } + + @SuppressWarnings("unused") + public void createUser(final String email, final String password, final String name, final UserCreateListener listener) { + createUser(email, password, name, null, listener); + } + + /** + * Refreshes the JWT authorization token. Tokens expire 60 minutes after they are issued, + * call this in order to get a fresh one without doing login again. + * + * @param requestListener a listener for the result state of the operation + */ + public void refreshToken(final TelepatRequestListener requestListener) { + Call call = apiClient.refreshToken(); + call.enqueue(new UserLoginCallback(requestInterceptor, internalDB, requestListener)); + } - @SuppressWarnings("unused") - public void createUser(final String email, final String password, final String name, final UserCreateListener listener) { - createUser(email, password, name, null, listener); - } - - /** - * Refreshes the JWT authorization token. Tokens expire 60 minutes after they are issued, - * call this in order to get a fresh one without doing login again. - * @param requestListener a listener for the result state of the operation - */ - public void refreshToken(final TelepatRequestListener requestListener) { - apiClient.refreshToken( - new UserLoginCallback( - requestInterceptor, - internalDB, - requestListener - ) - ); - } - - @SuppressWarnings("unused") - public void loginWithUsername(final String email, - final String password, - final TelepatRequestListener listener) { - if(email != null && password != null) { - HashMap userHash = new HashMap<>(); - userHash.put("username", email); - userHash.put("password", password); - apiClient.loginEmailAndPassword( - userHash, - new UserLoginCallback(requestInterceptor, internalDB, listener) - ); - } - } - - @SuppressWarnings("unused") - public void loginWithFacebook(final String fbToken, final String existingUsername, final TelepatRequestListener loginListener) { - apiClient.loginFacebook( - new RegisterFacebookUserRequest(fbToken, existingUsername).getParams(), - new UserLoginCallback(requestInterceptor, internalDB, loginListener) - ); - } - - @SuppressWarnings("unused") - public void loginWithFacebook(final String fbToken, final TelepatRequestListener loginListener) { - loginWithFacebook(fbToken, null, loginListener); - } - - @SuppressWarnings("unused") - public void loginWithTwitter(final String oauthToken, - final String oauthTokenSecret, - final TelepatRequestListener loginListener) { - apiClient.loginTwitter( - new RegisterTwitterUserRequest(oauthToken, oauthTokenSecret).getParams(), - new UserLoginCallback(requestInterceptor, internalDB, loginListener)); - } + @SuppressWarnings("unused") + public void loginWithUsername(final String email, + final String password, + final TelepatRequestListener listener) { + if (email != null && password != null) { + HashMap userHash = new HashMap<>(); + userHash.put("username", email); + userHash.put("password", password); + Call call = apiClient.loginEmailAndPassword(userHash); + call.enqueue(new UserLoginCallback(requestInterceptor, internalDB, listener)); + } + } + + @SuppressWarnings("unused") + public void loginWithFacebook(final String fbToken, final String existingUsername, final TelepatRequestListener loginListener) { + apiClient.loginFacebook(new RegisterFacebookUserRequest(fbToken, existingUsername).getParams()).enqueue(new UserLoginCallback(requestInterceptor, internalDB, loginListener)); + } + + @SuppressWarnings("unused") + public void loginWithFacebook(final String fbToken, final TelepatRequestListener loginListener) { + loginWithFacebook(fbToken, null, loginListener); + } + + @SuppressWarnings("unused") + public void loginWithTwitter(final String oauthToken, + final String oauthTokenSecret, + final TelepatRequestListener loginListener) { + apiClient.loginTwitter(new RegisterTwitterUserRequest(oauthToken, oauthTokenSecret).getParams()).enqueue(new UserLoginCallback(requestInterceptor, internalDB, loginListener)); + } /** * Send a Telepat Sync API call for logging out the current user. The method will return null if there is no currently logged in user. */ - @SuppressWarnings("unused") - public void logout() - { - apiClient.logout(new Callback>() { - @Override - public void success(HashMap userLogoutResponse, retrofit.client.Response response) { - TelepatLogger.log("Logout successful"); - requestInterceptor.setAuthorizationToken(null); - } - - @Override - public void failure(RetrofitError error) { - TelepatLogger.error("user logout failed - " + error.getMessage()); - } - }); - } - - /** - * Get information about the currently logged in user - * @return a HashMap of the user data. - */ - @SuppressWarnings("unused") - public Map getLoggedInUserInfo() { - Object userData = internalDB.getOperationsData(TelepatConstants.CURRENT_USER_DATA, null, HashMap.class); - if(userData instanceof HashMap) { - //noinspection unchecked - return (HashMap) userData; - } else { - TelepatLogger.error("Not a hashmap"); - return null; - } - } - - /** - * Request a password reset email - */ - @SuppressWarnings("unused") - public void requestPasswordResetEmail(String username, String callbackUrl, final TelepatRequestListener listener) { - HashMap requestBody = new HashMap<>(); - requestBody.put("username", username); - requestBody.put("type", "android"); - - if(callbackUrl != null && !callbackUrl.isEmpty()) { - requestBody.put("callbackUrl", callbackUrl); - } - - apiClient.requestPasswordReset(requestBody, new Callback>() { - @Override - public void success(HashMap genericApiResponse, Response response) { - TelepatLogger.log("Reset email sent"); - listener.onSuccess(); - } - - @Override - public void failure(RetrofitError error) { - TelepatLogger.log("Reset request failed"); - listener.onError(error); - } - }); - } - - @SuppressWarnings("unused") - public void requestPasswordResetEmail(String username, final TelepatRequestListener listener) { - requestPasswordResetEmail(username, null, listener); - } - - /** - * Commit password change request - * @param userId the user ID - * @param token the token received via the reset email / deep-link - * @param newPassword - * @param listener - */ - @SuppressWarnings("unused") - public void resetPassword(String userId, String token, String newPassword, final TelepatRequestListener listener) { - HashMap requestBody = new HashMap<>(); - requestBody.put("user_id", userId); - requestBody.put("token", token); - requestBody.put("password", newPassword); - apiClient.resetPassword(requestBody, new Callback>() { - @Override - public void success(HashMap genericApiResponse, Response response) { - TelepatLogger.log("Password was reset"); - listener.onSuccess(); - } - - @Override - public void failure(RetrofitError error) { - TelepatLogger.log("Password reset failed"); - listener.onError(error); - } - }); - } - - @SuppressWarnings("unused") - public void getUserMetadata(Callback callback) { - apiClient.getUserMetadata(callback); - } - - @SuppressWarnings("unused") - public void updateUserMetadata(List patches, String metadataId, final TelepatRequestListener listener) { - HashMap requestBody = new HashMap<>(); - ArrayList> jsonPatches = new ArrayList<>(); - for(UserUpdatePatch patch : patches) { - HashMap jsonPatch = new HashMap<>(); - jsonPatch.put("op", "replace"); - jsonPatch.put("path", "user_metadata/"+metadataId+"/"+patch.getFieldName()); - jsonPatch.put("value", patch.getFieldValue()); - jsonPatches.add(jsonPatch); - } - requestBody.put("patches", jsonPatches); - apiClient.updateUserMetadata(requestBody, new Callback>() { - @Override - public void success(HashMap response, Response response2) { - listener.onSuccess(); - } - - @Override - public void failure(RetrofitError error) { - listener.onError(error); - } - }); - } - - @SuppressWarnings("unused") - public void updateUserMetadata(UserUpdatePatch patch, String metadataId, final TelepatRequestListener listener) { - ArrayList patches = new ArrayList<>(); - patches.add(patch); - updateUserMetadata(patches, metadataId, listener); - } + @SuppressWarnings("unused") + public void logout() { + apiClient.logout().enqueue(new TelepatCallback() { + @Override + public void success(GenericApiResponse apiResponse) { + TelepatLogger.log("Logout successful"); + requestInterceptor.setAuthorizationToken(null); + } + + @Override + public void failure(ApiError error) { + TelepatLogger.error(error.message()); + } + + }); + } + + /** + * Get information about the currently logged in user + * + * @return a HashMap of the user data. + */ + @SuppressWarnings("unused") + public Map getLoggedInUserInfo() { + Object userData = internalDB.getOperationsData(TelepatConstants.CURRENT_USER_DATA, null, HashMap.class); + if (userData instanceof HashMap) { + //noinspection unchecked + return (HashMap) userData; + } else { + TelepatLogger.error("Not a hashmap"); + return null; + } + } + + /** + * Request a password reset email + */ + @SuppressWarnings("unused") + public void requestPasswordResetEmail(String username, String callbackUrl, final TelepatRequestListener listener) { + final HashMap requestBody = new HashMap<>(); + requestBody.put("username", username); + requestBody.put("type", "android"); + + if (callbackUrl != null && !callbackUrl.isEmpty()) { + requestBody.put("callbackUrl", callbackUrl); + } + apiClient.requestPasswordReset(requestBody).enqueue(new TelepatCallback() { + @Override + public void success(GenericApiResponse apiResponse) { + TelepatLogger.log("Reset email sent"); + listener.onSuccess(); + } + + @Override + public void failure(ApiError error) { + TelepatLogger.error(error.message()); + listener.onError(error); + } + + }); + } + + @SuppressWarnings("unused") + public void requestPasswordResetEmail(String username, final TelepatRequestListener listener) { + requestPasswordResetEmail(username, null, listener); + } + + /** + * Commit password change request + * + * @param userId the user ID + * @param token the token received via the reset email / deep-link + * @param newPassword + * @param listener + */ + @SuppressWarnings("unused") + public void resetPassword(String userId, String token, String newPassword, final TelepatRequestListener listener) { + HashMap requestBody = new HashMap<>(); + requestBody.put("user_id", userId); + requestBody.put("token", token); + requestBody.put("password", newPassword); + + apiClient.resetPassword(requestBody).enqueue(new TelepatCallback() { + @Override + public void success(GenericApiResponse apiResponse) { + TelepatLogger.log("Password was reset"); + listener.onSuccess(); + } + + @Override + public void failure(ApiError error) { + TelepatLogger.error(error.message()); + listener.onError(error); + } + + }); + } + + @SuppressWarnings("unused") + public void getUserMetadata(TelepatCallback callback) { + apiClient.getUserMetadata().enqueue(callback); + } + + @SuppressWarnings("unused") + public void updateUserMetadata(List patches, String metadataId, final TelepatRequestListener listener) { + HashMap requestBody = new HashMap<>(); + ArrayList> jsonPatches = new ArrayList<>(); + for (UserUpdatePatch patch : patches) { + HashMap jsonPatch = new HashMap<>(); + jsonPatch.put("op", "replace"); + jsonPatch.put("path", "user_metadata/" + metadataId + "/" + patch.getFieldName()); + jsonPatch.put("value", patch.getFieldValue()); + jsonPatches.add(jsonPatch); + } + requestBody.put("patches", jsonPatches); + + apiClient.updateUserMetadata(requestBody).enqueue(new TelepatCallback() { + @Override + public void success(GenericApiResponse apiResponse) { + listener.onSuccess(); + } + + @Override + public void failure(ApiError error) { + listener.onError(error); + } + }); + } + + @SuppressWarnings("unused") + public void updateUserMetadata(UserUpdatePatch patch, String metadataId, final TelepatRequestListener listener) { + ArrayList patches = new ArrayList<>(); + patches.add(patch); + updateUserMetadata(patches, metadataId, listener); + } /** * Create a new subscription to a Telepat channel - * @param context The context ID where the desired objects live in + * + * @param context The context ID where the desired objects live in * @param modelName The model name of the desired objects - * @param listener An object implementing OnChannelEventListener. All channel events will be sent - * to this object. - * @param type The desired Java class of the objects that will be emitted in this channel (should - * extend the TelepatBaseModel class) + * @param listener An object implementing OnChannelEventListener. All channel events will be sent + * to this object. + * @param type The desired Java class of the objects that will be emitted in this channel (should + * extend the TelepatBaseModel class) * @return a Channel object with the specified characteristics */ - @SuppressWarnings("unused") - public Channel subscribe(TelepatContext context, String modelName, OnChannelEventListener listener, Class type) { - Channel channel = new Channel.Builder(). + @SuppressWarnings("unused") + public Channel subscribe(TelepatContext context, String modelName, OnChannelEventListener listener, Class type) { + Channel channel = new Channel.Builder(). setContext(context). setModelName(modelName). setChannelEventListener(listener). setObjectType(type). build(); // subscriptions.put(channel.getSubscriptionIdentifier(), channel); - channel.subscribe(); - return channel; - } - - /** - * Create a new subscription to a Telepat channel - * @param context The context ID where the desired objects live in - * @param modelName The model name of the desired objects - * @param objectId The ID of an object to subscribe to. Can be null if not used. - * @param userId The user ID to filter results by. Can be null if not used. - * @param parentModelName The parent model name to filter results by. Can be null if not used. - * @param parentId The parent object ID to filter results by. Can be null if not used. - * @param filters A HashMap of filters. See http://docs.telepat.io/api.html#api-Object-ObjectSubscribe for details. Can be null if not used. - * @param type The desired Java class of the objects that will be emitted in this channel (should - * extend the TelepatBaseModel class) - * @param listener An object implementing OnChannelEventListener. All channel events will be sent - * to this object. - * @return a Channel object with the specified characteristics - */ - @Deprecated - @SuppressWarnings("unused") - public Channel subscribe(TelepatContext context, - String modelName, - String objectId, - String userId, - String parentModelName, - String parentId, - HashMap filters, - Class type, - OnChannelEventListener listener) { - Channel channel = new Channel.Builder() - .setContext(context) - .setModelName(modelName) - .setUserFilter(userId) - .setSingleObjectIdFilter(objectId) - .setParentFilter(parentModelName, parentId) - .setFilters(filters) - .setObjectType(type) - .setChannelEventListener(listener) - .build(); - channel.subscribe(); - return channel; - } - - /** - * Create a new subscription to a Telepat channel - * @param channel A channel object that covers all the desired characteristics. See Channel.Builder for ways to create a channel object. - */ - @SuppressWarnings("unused") - public void subscribe(Channel channel) { - channel.subscribe(); - } - - @SuppressWarnings("unused") - public void count(TelepatContext context, - String modelName, - String objectId, - String userId, - String parentModelName, - String parentId, - HashMap filters, - Channel.AggregationType aggregationType, - String aggregationField, - final TelepatCountCallback callback) { - - Channel channel = new Channel.Builder() - .setContext(context) - .setModelName(modelName) - .setUserFilter(userId) - .setSingleObjectIdFilter(objectId) - .setParentFilter(parentModelName, parentId) - .setFilters(filters) - .build(); - - channel.count(callback, aggregationType, aggregationField); - - } + channel.subscribe(); + return channel; + } + + /** + * Create a new subscription to a Telepat channel + * + * @param context The context ID where the desired objects live in + * @param modelName The model name of the desired objects + * @param objectId The ID of an object to subscribe to. Can be null if not used. + * @param userId The user ID to filter results by. Can be null if not used. + * @param parentModelName The parent model name to filter results by. Can be null if not used. + * @param parentId The parent object ID to filter results by. Can be null if not used. + * @param filters A HashMap of filters. See http://docs.telepat.io/api.html#api-Object-ObjectSubscribe for details. Can be null if not used. + * @param type The desired Java class of the objects that will be emitted in this channel (should + * extend the TelepatBaseModel class) + * @param listener An object implementing OnChannelEventListener. All channel events will be sent + * to this object. + * @return a Channel object with the specified characteristics + */ + @Deprecated + @SuppressWarnings("unused") + public Channel subscribe(TelepatContext context, + String modelName, + String objectId, + String userId, + String parentModelName, + String parentId, + HashMap filters, + Class type, + OnChannelEventListener listener) { + Channel channel = new Channel.Builder() + .setContext(context) + .setModelName(modelName) + .setUserFilter(userId) + .setSingleObjectIdFilter(objectId) + .setParentFilter(parentModelName, parentId) + .setFilters(filters) + .setObjectType(type) + .setChannelEventListener(listener) + .build(); + channel.subscribe(); + return channel; + } + + /** + * Create a new subscription to a Telepat channel + * + * @param channel A channel object that covers all the desired characteristics. See Channel.Builder for ways to create a channel object. + */ + @SuppressWarnings("unused") + public void subscribe(Channel channel) { + channel.subscribe(); + } + + @SuppressWarnings("unused") + public void count(TelepatContext context, + String modelName, + String objectId, + String userId, + String parentModelName, + String parentId, + HashMap filters, + Channel.AggregationType aggregationType, + String aggregationField, + final TelepatCountCallback callback) { + + Channel channel = new Channel.Builder() + .setContext(context) + .setModelName(modelName) + .setUserFilter(userId) + .setSingleObjectIdFilter(objectId) + .setParentFilter(parentModelName, parentId) + .setFilters(filters) + .build(); + + channel.count(callback, aggregationType, aggregationField); + + } /** * Get a Map of all curently active contexts for the Telepat Application + * * @return A Map instance containing TelepatContext objects stored by their ID */ - public Map getContexts() { return mServerContexts; } + public Map getContexts() { + return mServerContexts; + } /** * Remove a locally registered subscription of a Telepat Channel object (this does not send any * notifications to the Telepat Sync API + * * @param mChannel The channel instance */ @SuppressWarnings("unused") - public void removeSubscription(Channel mChannel) { + public void removeSubscription(Channel mChannel) { mChannel.unsubscribe(); subscriptions.remove(mChannel.getSubscriptionIdentifier()); } @@ -708,6 +746,7 @@ public void removeSubscription(Channel mChannel) { /** * Locally register an active subscription to a Telepat Channel with the Telepat SDK instance * (new channel objects register themselves automatically) + * * @param mChannel The channel object to be registered */ public void registerSubscription(Channel mChannel) { @@ -716,239 +755,230 @@ public void registerSubscription(Channel mChannel) { /** * Get the Channel instance of a locally registered channel. + * * @param channelIdentifier A properly formatted string of the channel identifier. * @return the Channel instance */ - public Channel getSubscribedChannel(String channelIdentifier) { - return subscriptions.get(channelIdentifier); - } + public Channel getSubscribedChannel(String channelIdentifier) { + return subscriptions.get(channelIdentifier); + } /** * Get a unique device identifier. Used internally for detecting already registered devices + * * @return A String containing the UDID */ - public String getDeviceLocalIdentifier() { - if(localUdid!=null) return localUdid; - String androidId = android.provider.Settings. - System.getString(mContext.getContentResolver(), - android.provider.Settings.Secure.ANDROID_ID); + public String getDeviceLocalIdentifier() { + if (localUdid != null) return localUdid; + String androidId = android.provider.Settings. + System.getString(mContext.getContentResolver(), + android.provider.Settings.Secure.ANDROID_ID); - localUdid = (String) internalDB.getOperationsData(TelepatConstants.LOCAL_UDID_KEY, - androidId, - String.class); + localUdid = (String) internalDB.getOperationsData(TelepatConstants.LOCAL_UDID_KEY, + androidId, + String.class); - return localUdid; - } + return localUdid; + } /** * Set the unique device identifier sent to the Telepat cloud. This method should be used as * early as possible, before registering the device with the Sync API. + * * @param udid the desired UDID */ - @SuppressWarnings("unused") - public void setDeviceLocalIdentifier(String udid) { - internalDB.setOperationsData(TelepatConstants.LOCAL_UDID_KEY, udid); - } - - public void registerContextUpdateListener(ContextUpdateListener listener) { - this.contextUpdateListeners.add(listener); - } - - @SuppressWarnings("unused") - public void removeContextUpdateListener(ContextUpdateListener listener) { - this.contextUpdateListeners.remove(listener); - } - - @SuppressWarnings("unused") - public void updateUser(final ArrayList userChanges, String userId, final TelepatRequestListener listener) { - HashMap requestBody = new HashMap<>(); - ArrayList> jsonPatches = new ArrayList<>(); - for(UserUpdatePatch patch : userChanges) { - HashMap jsonPatch = new HashMap<>(); - jsonPatch.put("op", "replace"); - jsonPatch.put("path", "user/"+userId+"/"+patch.getFieldName()); - jsonPatch.put("value", patch.getFieldValue()); - jsonPatches.add(jsonPatch); - } - requestBody.put("patches", jsonPatches); - apiClient.updateUser(requestBody, new Callback>() { - @Override - public void success(HashMap genericApiResponse, Response response) { - TelepatLogger.log("User update successful"); - if (getLoggedInUserInfo() != null) { - HashMap userData = new HashMap<>(getLoggedInUserInfo()); - for (UserUpdatePatch patch : userChanges) { - userData.put(patch.getFieldName(), patch.getFieldValue()); - } - internalDB.setOperationsData(TelepatConstants.CURRENT_USER_DATA, userData); - } - listener.onSuccess(); - } - - @Override - public void failure(RetrofitError error) { - TelepatLogger.log("User update failed"); - listener.onError(error); - } - }); - } - - /** - * Method for notifying listeners of updates to context objects. Used internally by transports - * for firing notification updated. - * @param notification a TransportNotification instance that encapsulates changes made to a context - */ - public void fireContextUpdate(TransportNotification notification) { - if(mServerContexts == null ) return; - Gson gson = new Gson(); - TelepatContext ctx; - String contextId; - switch (notification.getNotificationType()) { - case ObjectAdded: - ctx = gson.fromJson(notification.getNotificationValue(), TelepatContext.class); - mServerContexts.put(ctx.getId(), ctx); - for (ContextUpdateListener listener : this.contextUpdateListeners) { - listener.contextAdded(ctx); - } - break; - case ObjectUpdated: - String[] pathSegments = notification.getNotificationPath().getAsString().replace("context/", "").split("/"); - contextId = pathSegments[0]; - String fieldName = pathSegments[1]; - if(mServerContexts.containsKey(contextId)) { - ctx = mServerContexts.get(contextId); - switch (fieldName) { - case "meta": - Type type = new TypeToken>(){}.getType(); - HashMap meta = gson.fromJson(notification.getNotificationValue().toString(), type); - ctx.getMeta().putAll(meta); - break; - case "name": - ctx.setName(notification.getNotificationValue().getAsString()); - } - mServerContexts.put(ctx.getId(), ctx); - for (ContextUpdateListener listener : this.contextUpdateListeners) { - listener.contextUpdated(ctx); - } - } - break; - case ObjectDeleted: - contextId = notification.getNotificationPath().getAsString().replace("context/",""); - if(mServerContexts.containsKey(contextId)) { - ctx = mServerContexts.get(contextId); - mServerContexts.remove(contextId); - for (ContextUpdateListener listener : this.contextUpdateListeners) { - listener.contextEnded(ctx); - } - } - break; - } - } - - @SuppressWarnings("unused") - public void sendProxiedRequest(TelepatProxyRequest request, final TelepatProxyResponse callback) { - apiClient.proxy(request, new Callback() { - @Override - public void success(Response response, Response response2) { - //Try to get response body - BufferedReader reader = null; - StringBuilder sb = new StringBuilder(); - try { - - reader = new BufferedReader(new InputStreamReader(response.getBody().in())); - String line; - - try { - while ((line = reader.readLine()) != null) { - sb.append(line); - } - } catch (IOException e) { - e.printStackTrace(); - } - } catch (IOException e) { - e.printStackTrace(); - } - - String responseBody = sb.toString(); - if(callback!=null) { - callback.onRequestFinished(responseBody, response.getHeaders()); - } - } - - @Override - public void failure(RetrofitError error) { - if(callback!=null) { - callback.onTelepatError(error); - } - } - }); - } - - @SuppressWarnings("unused") - public void sendEmail(List recipients, String from, String fromName, String subject, String body, Callback callback) { - HashMap requestBody = new HashMap<>(); - if(recipients==null || from==null || body==null) { - callback.failure(null); - return; - } - ArrayList recipientsList = new ArrayList<>(recipients); - requestBody.put("recipients", recipientsList); - requestBody.put("from", from); - if(fromName!=null) { - requestBody.put("from_name", fromName); - } - if(subject!=null) { - requestBody.put("subject", subject); - } - requestBody.put("body", body); - apiClient.sendEmail(requestBody, callback); - } - - @SuppressWarnings("unused") - public void me(Callback callback) { - getAPIInstance().me(callback); - } - - @SuppressWarnings("unused") - public void get(String userId, Callback callback) { - getAPIInstance().get(userId, callback); - } - - public String getAppId() { - return appId; - } - - @SuppressWarnings("unused") - public void appendToIndexedList(Map objectToIndex, String listName, String indexedPropertyName, Callback callback) { - HashMap appendRequestBody = new HashMap<>(); - appendRequestBody.put("listName", listName); - appendRequestBody.put("indexedProperty", indexedPropertyName); - appendRequestBody.put("memberObject", objectToIndex); - getAPIInstance().appendToIndexedList(appendRequestBody, callback); - } - - @SuppressWarnings("unused") - public void objectsExistsInIndex(List memberPropertyValues, String listName, String indexedPropertyName, Callback callback) { - HashMap requestBody = new HashMap<>(); - requestBody.put("listName", listName); - requestBody.put("indexedProperty", indexedPropertyName); - requestBody.put("members", memberPropertyValues); - getAPIInstance().checkIndexedListMembers(requestBody, callback); - } - - @SuppressWarnings("unused") - public void deleteIndexedList(String listName, Callback callback) { - HashMap requestBody = new HashMap<>(); - requestBody.put("listName", listName); - getAPIInstance().deleteIndexedList(requestBody, callback); - } - - @SuppressWarnings("unused") - public void removeMemberFromIndexedList(String memberPropertyValue, String listName, String indexedPropertyName, Callback callback) { - HashMap requestBody = new HashMap<>(); - requestBody.put("listName", listName); - requestBody.put("indexedProperty", indexedPropertyName); - requestBody.put("member", memberPropertyValue); - getAPIInstance().removeFromIndexedList(requestBody, callback); - } + @SuppressWarnings("unused") + public void setDeviceLocalIdentifier(String udid) { + internalDB.setOperationsData(TelepatConstants.LOCAL_UDID_KEY, udid); + } + + public void registerContextUpdateListener(ContextUpdateListener listener) { + this.contextUpdateListeners.add(listener); + } + + @SuppressWarnings("unused") + public void removeContextUpdateListener(ContextUpdateListener listener) { + this.contextUpdateListeners.remove(listener); + } + + @SuppressWarnings("unused") + public void updateUser(final ArrayList userChanges, String userId, final TelepatRequestListener listener) { + final HashMap requestBody = new HashMap<>(); + ArrayList> jsonPatches = new ArrayList<>(); + for (UserUpdatePatch patch : userChanges) { + HashMap jsonPatch = new HashMap<>(); + jsonPatch.put("op", "replace"); + jsonPatch.put("path", "user/" + userId + "/" + patch.getFieldName()); + jsonPatch.put("value", patch.getFieldValue()); + jsonPatches.add(jsonPatch); + } + requestBody.put("patches", jsonPatches); + + apiClient.updateUser(requestBody).enqueue(new TelepatCallback() { + @Override + public void success(GenericApiResponse apiResponse) { + if (getLoggedInUserInfo() != null) { + HashMap userData = new HashMap<>(getLoggedInUserInfo()); + for (UserUpdatePatch patch : userChanges) { + userData.put(patch.getFieldName(), patch.getFieldValue()); + } + internalDB.setOperationsData(TelepatConstants.CURRENT_USER_DATA, userData); + } + listener.onSuccess(); + } + + @Override + public void failure(ApiError error) { + listener.onError(error); + } + + }); + } + + /** + * Method for notifying listeners of updates to context objects. Used internally by transports + * for firing notification updated. + * + * @param notification a TransportNotification instance that encapsulates changes made to a context + */ + public void fireContextUpdate(TransportNotification notification) { + if (mServerContexts == null) return; + Gson gson = new Gson(); + TelepatContext ctx; + String contextId; + switch (notification.getNotificationType()) { + case ObjectAdded: + ctx = gson.fromJson(notification.getNotificationValue(), TelepatContext.class); + mServerContexts.put(ctx.getId(), ctx); + for (ContextUpdateListener listener : this.contextUpdateListeners) { + listener.contextAdded(ctx); + } + break; + case ObjectUpdated: + String[] pathSegments = notification.getNotificationPath().getAsString().replace("context/", "").split("/"); + contextId = pathSegments[0]; + String fieldName = pathSegments[1]; + if (mServerContexts.containsKey(contextId)) { + ctx = mServerContexts.get(contextId); + switch (fieldName) { + case "meta": + Type type = new TypeToken>() { + }.getType(); + HashMap meta = gson.fromJson(notification.getNotificationValue().toString(), type); + ctx.getMeta().putAll(meta); + break; + case "name": + ctx.setName(notification.getNotificationValue().getAsString()); + } + mServerContexts.put(ctx.getId(), ctx); + for (ContextUpdateListener listener : this.contextUpdateListeners) { + listener.contextUpdated(ctx); + } + } + break; + case ObjectDeleted: + contextId = notification.getNotificationPath().getAsString().replace("context/", ""); + if (mServerContexts.containsKey(contextId)) { + ctx = mServerContexts.get(contextId); + mServerContexts.remove(contextId); + for (ContextUpdateListener listener : this.contextUpdateListeners) { + listener.contextEnded(ctx); + } + } + break; + } + } + + @SuppressWarnings("unused") + public void sendProxiedRequest(TelepatProxyRequest request, final TelepatProxyResponse callback) { + apiClient.proxy(request).enqueue(new Callback() { + @Override + public void onResponse(Call call, Response response) { + if (response.isSuccessful()) { + String responseBody = response.body().toString(); + if (callback != null) { + callback.onRequestFinished(responseBody, response.headers()); + } + } else { + if (callback != null) { + callback.onTelepatError(ApiError.parseError(response)); + } + } + } + + @Override + public void onFailure(Call call, Throwable t) { + TelepatLogger.error(t.getMessage()); + t.printStackTrace(); + } + }); + } + + @SuppressWarnings("unused") + public void sendEmail(List recipients, String from, String fromName, String subject, String body, TelepatCallback callback) { + HashMap requestBody = new HashMap<>(); + if (recipients == null || from == null || body == null) { + callback.onFailure(null, null); + return; + } + ArrayList recipientsList = new ArrayList<>(recipients); + requestBody.put("recipients", recipientsList); + requestBody.put("from", from); + if (fromName != null) { + requestBody.put("from_name", fromName); + } + if (subject != null) { + requestBody.put("subject", subject); + } + requestBody.put("body", body); + apiClient.sendEmail(requestBody).enqueue(callback); + } + + @SuppressWarnings("unused") + public void me(TelepatCallback callback) { + getAPIInstance().me().enqueue(callback); + } + + @SuppressWarnings("unused") + public void get(String userId, Callback callback) { + getAPIInstance().get(userId).enqueue(callback); + } + + public String getAppId() { + return appId; + } + + @SuppressWarnings("unused") + public void appendToIndexedList(Map objectToIndex, String listName, String indexedPropertyName, Callback callback) { + HashMap appendRequestBody = new HashMap<>(); + appendRequestBody.put("listName", listName); + appendRequestBody.put("indexedProperty", indexedPropertyName); + appendRequestBody.put("memberObject", objectToIndex); + getAPIInstance().appendToIndexedList(appendRequestBody).enqueue(callback); + } + + @SuppressWarnings("unused") + public void objectsExistsInIndex(List memberPropertyValues, String listName, String indexedPropertyName, Callback callback) { + HashMap requestBody = new HashMap<>(); + requestBody.put("listName", listName); + requestBody.put("indexedProperty", indexedPropertyName); + requestBody.put("members", memberPropertyValues); + getAPIInstance().checkIndexedListMembers(requestBody).enqueue(callback); + } + + @SuppressWarnings("unused") + public void deleteIndexedList(String listName, Callback callback) { + HashMap requestBody = new HashMap<>(); + requestBody.put("listName", listName); + getAPIInstance().deleteIndexedList(requestBody).enqueue(callback); + } + + @SuppressWarnings("unused") + public void removeMemberFromIndexedList(String memberPropertyValue, String listName, String indexedPropertyName, Callback callback) { + HashMap requestBody = new HashMap<>(); + requestBody.put("listName", listName); + requestBody.put("indexedProperty", indexedPropertyName); + requestBody.put("member", memberPropertyValue); + getAPIInstance().removeFromIndexedList(requestBody).enqueue(callback); + } } diff --git a/src/main/java/io/telepat/sdk/models/Channel.java b/src/main/java/io/telepat/sdk/models/Channel.java index 8e2ac9b..7d8cb08 100644 --- a/src/main/java/io/telepat/sdk/models/Channel.java +++ b/src/main/java/io/telepat/sdk/models/Channel.java @@ -17,12 +17,13 @@ import io.telepat.sdk.data.TelepatInternalDB; import io.telepat.sdk.networking.CrudOperationsCallback; import io.telepat.sdk.networking.OctopusApi; +import io.telepat.sdk.networking.responses.ApiError; import io.telepat.sdk.networking.responses.GenericApiResponse; import io.telepat.sdk.networking.responses.TelepatCountCallback; import io.telepat.sdk.utilities.TelepatLogger; -import retrofit.Callback; -import retrofit.RetrofitError; -import retrofit.client.Response; +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Response; /** * Created by Andrei Marinescu, catalinivan on 09/03/15. @@ -135,54 +136,46 @@ private void linkExternalDependencies() { * If the device is already registered, the stored objects will be notified again. */ private void doSubscribe(int offset, int limit, boolean justInitialState) { - apiInstance.subscribe( - getSubscribingRequestBody(offset, limit, justInitialState), - new Callback>() { - @Override - public void success( - HashMap responseHashMap, - Response response) { - - Integer status = Integer.parseInt(responseHashMap.get("status").toString()); - JsonElement message = responseHashMap.get("content"); - - if (status == 200) { - Telepat.getInstance().registerSubscription(Channel.this); - - for (JsonElement entry - : message.getAsJsonArray()) { - processNotification(new TransportNotification(entry)); - } - - if (Channel.this.mChannelEventListener != null) { - mChannelEventListener.onSubscribeComplete(); - } - - } else { - if (Channel.this.mChannelEventListener != null) - Channel.this.mChannelEventListener.onError(status, message.toString()); - } + apiInstance.subscribe(getSubscribingRequestBody(offset, limit, justInitialState)).enqueue(new TelepatCallback() { + @Override + public void success(GenericApiResponse apiResponse) { + Integer status = apiResponse.status; + JsonElement message = apiResponse.content; + if (status == 200) { + Telepat.getInstance().registerSubscription(Channel.this); + + for (JsonElement entry : message.getAsJsonArray()) { + processNotification(new TransportNotification(entry)); } - @Override - public void failure(RetrofitError error) { - if (error!=null && error.getResponse()!=null && error.getResponse().getStatus()==409) { - TelepatLogger.log("There is an already active subscription for this channel."); - if (Channel.this.mChannelEventListener != null) { - mChannelEventListener.onSubscribeComplete(); - } - } else if (error!=null && error.getResponse()!=null && error.getResponse().getStatus()==401) { - TelepatLogger.log("Not logged in."); - } else if(error!=null && error.getMessage()!=null){ - TelepatLogger.log("Error subscribing: " + error.getMessage()); - } else { - TelepatLogger.log("Error subscribing with unknown error"); - } - if (mChannelEventListener != null) { - mChannelEventListener.onError(error.getResponse().getStatus(), error.getMessage()); - } + if (Channel.this.mChannelEventListener != null) { + mChannelEventListener.onSubscribeComplete(); + } + + }else{ + if (Channel.this.mChannelEventListener != null) + Channel.this.mChannelEventListener.onError(status, message.toString()); + } + } + + @Override + public void failure(ApiError error) { + if(error.status() == 409){ + TelepatLogger.log("There is an already active subscription for this channel."); + if (Channel.this.mChannelEventListener != null) { + mChannelEventListener.onSubscribeComplete(); } - }); + }else if (error.status() == 401){ + TelepatLogger.log("Not logged in."); + }else { + TelepatLogger.log("Error subscribing: " + error.message()); + } + + if (mChannelEventListener != null) { + mChannelEventListener.onError(error.status(), error.message()); + } + } + }); } public void subscribe() { @@ -217,21 +210,25 @@ public void count(final TelepatCountCallback callback, AggregationType aggregati break; } } - apiInstance.count( - countRequestBody, - new Callback() { - @Override - public void success(GenericApiResponse genericApiResponse, Response response) { - int countValue = ((Double) genericApiResponse.content.get("count")).intValue(); - Double aggregationValue = ((Double) genericApiResponse.content.get("aggregation")); - callback.onSuccess(countValue, aggregationValue); - } - @Override - public void failure(RetrofitError error) { - callback.onFailure(error); - } - }); + apiInstance.count(countRequestBody).enqueue(new Callback() { + @Override + public void onResponse(Call call, Response response) { + if(response.isSuccessful()) { + int countValue = ((Double) response.body().getContent().get("count")).intValue(); + Double aggregationValue = ((Double) response.body().getContent().get("aggregation")); + callback.onSuccess(countValue, aggregationValue); + }else{ + callback.onFailure(ApiError.parseError(response).message()); + } + + } + + @Override + public void onFailure(Call call, Throwable t) { + TelepatLogger.error(t.getMessage()); + } + }); } /** @@ -321,22 +318,23 @@ public HashMap getDeleteRequestBody(TelepatBaseModel object) { * Unsubscribes this device from receiving further updates from this channel */ public void unsubscribe() { - Telepat.getInstance() - .getAPIInstance() - .unsubscribe(getSubscribingRequestBody(), - new Callback>() { - @Override - public void success(HashMap integerStringHashMap, Response response) { - TelepatLogger.log("Unsubscribed"); - dbInstance. - deleteChannelObjects(Channel.this.getSubscriptionIdentifier()); - } - - @Override - public void failure(RetrofitError error) { - TelepatLogger.log("Unsubscribe failed: " + error.getMessage()); - } - }); + Telepat.getInstance().getAPIInstance().unsubscribe(getSubscribingRequestBody()).enqueue(new Callback() { + @Override + public void onResponse(Call call, Response response) { + if(response.isSuccessful()){ + TelepatLogger.log("Unsubscribed"); + dbInstance. + deleteChannelObjects(Channel.this.getSubscriptionIdentifier()); + }else { + TelepatLogger.log("Unsubscribe failed: " + ApiError.parseError(response).message()); + } + } + + @Override + public void onFailure(Call call, Throwable t) { + TelepatLogger.error(t.getMessage()); + } + }); } /** @@ -348,7 +346,7 @@ public String add(TelepatBaseModel object) { //TODO add a proper uuid object.setUuid(""+System.currentTimeMillis()); waitingForCreation.put(object.getUuid(), object); - apiInstance.create(getCreateRequestBody(object), new CrudOperationsCallback("Create")); + apiInstance.create(getCreateRequestBody(object)).enqueue(new CrudOperationsCallback("Create")); return object.getUuid(); } @@ -357,7 +355,7 @@ public String add(TelepatBaseModel object) { * @param object an object of a class extending TelepatBaseModel */ public void remove(TelepatBaseModel object) { - apiInstance.delete(getDeleteRequestBody(object), new CrudOperationsCallback("Delete")); + apiInstance.delete(getDeleteRequestBody(object)).enqueue(new CrudOperationsCallback("Delete")); } /** @@ -582,7 +580,7 @@ public void propertyChange(PropertyChangeEvent event) { this.mModelName+"/"+obj.getId()+"/"+event.getPropertyName(), event.getNewValue(), obj.getId()); - apiInstance.update(getUpdateRequestBody(patch), new CrudOperationsCallback("Update")); + apiInstance.update(getUpdateRequestBody(patch)).enqueue(new CrudOperationsCallback("Update")); } } diff --git a/src/main/java/io/telepat/sdk/models/TelepatCallback.java b/src/main/java/io/telepat/sdk/models/TelepatCallback.java new file mode 100644 index 0000000..5cf9731 --- /dev/null +++ b/src/main/java/io/telepat/sdk/models/TelepatCallback.java @@ -0,0 +1,62 @@ +package io.telepat.sdk.models; + +import io.telepat.sdk.Telepat; +import io.telepat.sdk.networking.responses.ApiError; +import io.telepat.sdk.networking.responses.GenericApiResponse; +import io.telepat.sdk.utilities.TelepatConstants; +import io.telepat.sdk.utilities.TelepatLogger; +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Response; + +/** + * Created by ovidiuluca on 14/10/2016. + */ + +public abstract class TelepatCallback implements Callback { + + /** + * isRefreshTokenCalled is used to make one single request for refreshToken + * */ + private boolean isRefreshTokenCalled = false; + + public abstract void success(GenericApiResponse apiResponse); + + public abstract void failure(ApiError error); + + @Override + public void onResponse(Call call, Response response) { + if (response.isSuccessful()) { + success(response.body()); + } else { + final ApiError apiError = ApiError.parseError(response); + if ((apiError.code().equals(TelepatConstants.CODE_TOKEN_EXPIRED) && apiError.status() == 401) || + (apiError.code().equals("002") && apiError.status() == 500) || + (apiError.code().equals(TelepatConstants.CODE_TOKEN_EXPIRED) && apiError.status() == 400)) { + final Call newCall = call.clone(); + if(!isRefreshTokenCalled) { + isRefreshTokenCalled = true; + Telepat.getInstance().refreshToken(new TelepatRequestListener() { + @Override + public void onSuccess() { + newCall.enqueue(TelepatCallback.this); + } + + @Override + public void onError(ApiError error) { + failure(apiError); + } + + }); + } + }else{ + failure(apiError); + } + } + } + + @Override + public void onFailure(Call call, Throwable t) { + TelepatLogger.error(t.getMessage()); + } +} diff --git a/src/main/java/io/telepat/sdk/models/TelepatProxyResponse.java b/src/main/java/io/telepat/sdk/models/TelepatProxyResponse.java index 5882b15..323e6e6 100644 --- a/src/main/java/io/telepat/sdk/models/TelepatProxyResponse.java +++ b/src/main/java/io/telepat/sdk/models/TelepatProxyResponse.java @@ -1,15 +1,14 @@ package io.telepat.sdk.models; -import java.util.List; -import retrofit.RetrofitError; -import retrofit.client.Header; +import io.telepat.sdk.networking.responses.ApiError; +import okhttp3.Headers; /** * Created by andrei on 3/21/16. * */ public interface TelepatProxyResponse { - void onRequestFinished(String responseBody, List

responseHeaders); - void onTelepatError(RetrofitError error); + void onRequestFinished(String responseBody, Headers responseHeaders); + void onTelepatError(ApiError error); } diff --git a/src/main/java/io/telepat/sdk/models/TelepatRequestListener.java b/src/main/java/io/telepat/sdk/models/TelepatRequestListener.java index adc29f7..a461d04 100644 --- a/src/main/java/io/telepat/sdk/models/TelepatRequestListener.java +++ b/src/main/java/io/telepat/sdk/models/TelepatRequestListener.java @@ -1,11 +1,11 @@ package io.telepat.sdk.models; -import retrofit.RetrofitError; +import io.telepat.sdk.networking.responses.ApiError; /** * Created by andrei on 11/8/15. */ public interface TelepatRequestListener { void onSuccess(); - void onError(RetrofitError error); + void onError(ApiError error); } diff --git a/src/main/java/io/telepat/sdk/models/UserCreateListener.java b/src/main/java/io/telepat/sdk/models/UserCreateListener.java index 069fd7e..b9e5273 100644 --- a/src/main/java/io/telepat/sdk/models/UserCreateListener.java +++ b/src/main/java/io/telepat/sdk/models/UserCreateListener.java @@ -1,11 +1,11 @@ package io.telepat.sdk.models; -import retrofit.RetrofitError; +import io.telepat.sdk.networking.responses.ApiError; /** * Created by andrei on 11/8/15. */ public interface UserCreateListener { public void onUserCreateSuccess(); - public void onUserCreateFailure(RetrofitError error); + public void onUserCreateFailure(ApiError error); } diff --git a/src/main/java/io/telepat/sdk/models/UserLoginCallback.java b/src/main/java/io/telepat/sdk/models/UserLoginCallback.java index 67b4967..fb6958f 100644 --- a/src/main/java/io/telepat/sdk/models/UserLoginCallback.java +++ b/src/main/java/io/telepat/sdk/models/UserLoginCallback.java @@ -4,18 +4,16 @@ import io.telepat.sdk.data.TelepatInternalDB; import io.telepat.sdk.networking.OctopusRequestInterceptor; +import io.telepat.sdk.networking.responses.ApiError; import io.telepat.sdk.networking.responses.GenericApiResponse; import io.telepat.sdk.utilities.TelepatConstants; import io.telepat.sdk.utilities.TelepatLogger; -import retrofit.Callback; -import retrofit.RetrofitError; -import retrofit.client.Response; /** * Created by Andrei on 11.02.2016. * Retrofit callback implementation for user login requests. */ -public class UserLoginCallback implements Callback { +public class UserLoginCallback extends TelepatCallback { private OctopusRequestInterceptor interceptor; private TelepatRequestListener loginListener; @@ -29,36 +27,37 @@ public UserLoginCallback(OctopusRequestInterceptor interceptor, this.loginListener = loginListener; } + + private void persistLoginData(HashMap loginData) { +// String expiredToken = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6Im92aWRpdS5sdWNhQGFwcHNjZW5kLmNvbSIsImlkIjoiODM3ZmM5NWItOGRmNi00OWIzLWFjOWQtYWRiODgxNWI3MzE4IiwiaWF0IjoxNDc2MTExNTkxLCJleHAiOjE0NzYxMTUxOTF9.5uHdM3qXzYk-dD87rVoqvV92rweomRQce1AdnAY0Dr8"; + internalDB.setOperationsData(TelepatConstants.JWT_KEY, loginData.get("token")); + interceptor.setAuthorizationToken((String) loginData.get("token")); + + TelepatLogger.log("token::: " + interceptor.getAuthorizationToken()); + + if(loginData.containsKey("user")) { + internalDB.setOperationsData(TelepatConstants.CURRENT_USER_DATA, loginData.get("user")); + } + } + @Override - public void success(GenericApiResponse genericApiResponse, Response response) { - persistLoginData(genericApiResponse.content); + public void success(GenericApiResponse apiResponse) { + persistLoginData(apiResponse.getContent()); TelepatLogger.log("User logged in"); - if(loginListener != null) + if (loginListener != null) loginListener.onSuccess(); } @Override - public void failure(RetrofitError error) { - if(error!=null && error.getResponse()!=null && error.getResponse().getStatus()==409) { + public void failure(ApiError error) { + if (error.status() == 409) { TelepatLogger.log("A facebook user with that fid already exists."); } else { TelepatLogger.log("User login failed."); } - if(loginListener != null) - loginListener.onError(error); - } - - - private void persistLoginData(HashMap loginData) { - if(loginData.containsKey("token")) { - internalDB.setOperationsData(TelepatConstants.JWT_KEY, loginData.get("token")); -// internalDB.setOperationsData(TelepatConstants.JWT_TIMESTAMP_KEY, System.currentTimeMillis()); - interceptor.setAuthorizationToken((String) loginData.get("token")); - } - if(loginData.containsKey("user")) { - internalDB.setOperationsData(TelepatConstants.CURRENT_USER_DATA, loginData.get("user")); - } + if (loginListener != null) + loginListener.onError(error); } } diff --git a/src/main/java/io/telepat/sdk/networking/CrudOperationsCallback.java b/src/main/java/io/telepat/sdk/networking/CrudOperationsCallback.java index c4e2652..95d2f02 100644 --- a/src/main/java/io/telepat/sdk/networking/CrudOperationsCallback.java +++ b/src/main/java/io/telepat/sdk/networking/CrudOperationsCallback.java @@ -1,17 +1,15 @@ package io.telepat.sdk.networking; -import java.util.HashMap; - +import io.telepat.sdk.models.TelepatCallback; +import io.telepat.sdk.networking.responses.ApiError; +import io.telepat.sdk.networking.responses.GenericApiResponse; import io.telepat.sdk.utilities.TelepatLogger; -import retrofit.Callback; -import retrofit.RetrofitError; -import retrofit.client.Response; /** * Created by Andrei Marinescu on 22.06.2015. * Common Callback implementation for CRUD operations with OctopusApi */ -public class CrudOperationsCallback implements Callback> { +public class CrudOperationsCallback extends TelepatCallback { private String opType; public CrudOperationsCallback(String opType) { @@ -19,15 +17,14 @@ public CrudOperationsCallback(String opType) { } @Override - public void success(HashMap apiResponse, Response response) { - if(apiResponse.get("status").equals("202")) - TelepatLogger.log(opType+" successful: " + apiResponse.get("message")); - else - TelepatLogger.error(opType+" failed: "+apiResponse.get("message")); + public void success(GenericApiResponse apiResponse) { + if (apiResponse.status == 202) + TelepatLogger.log(opType + " successful: " + apiResponse.content); } @Override - public void failure(RetrofitError error) { - TelepatLogger.log(opType+" failed: " + error.getMessage()); + public void failure(ApiError error) { + TelepatLogger.error(opType + " failed: " + error.message()); } + } diff --git a/src/main/java/io/telepat/sdk/networking/OctopusApi.java b/src/main/java/io/telepat/sdk/networking/OctopusApi.java index 246e77b..7ea41ea 100644 --- a/src/main/java/io/telepat/sdk/networking/OctopusApi.java +++ b/src/main/java/io/telepat/sdk/networking/OctopusApi.java @@ -8,12 +8,12 @@ import io.telepat.sdk.models.TelepatProxyRequest; import io.telepat.sdk.networking.responses.ContextsApiResponse; import io.telepat.sdk.networking.responses.GenericApiResponse; -import retrofit.Callback; -import retrofit.client.Response; -import retrofit.http.Body; -import retrofit.http.GET; -import retrofit.http.POST; -import retrofit.http.Query; +import retrofit2.Call; +import retrofit2.Response; +import retrofit2.http.Body; +import retrofit2.http.GET; +import retrofit2.http.POST; +import retrofit2.http.Query; /** * Created by Andrei Marinescu on 02.06.2015. @@ -24,173 +24,158 @@ public interface OctopusApi { /** * Method for sending a device registration request * @param body - * @param cb + * @return call */ @POST("/device/register") - void registerDevice(@Body Map body, Callback cb); + Call registerDevice(@Body Map body); /** * Method for retrieving all active contexts - * @param cb + * @return call */ @POST("/context/all") - void updateContexts(Callback cb); + Call updateContexts(); @Deprecated @GET("/context/all") - void updateContextsCompat(Callback cb); + Call updateContextsCompat(); /** * Method for sending a register request using the Facebook auth provider * @param body - * @param cb */ @POST("/user/register-facebook") - void registerUserFacebook(@Body Map body, Callback> cb); + Call registerUserFacebook(@Body Map body); /** * Method for sending a register request using the Email/Password auth provider * @param body - * @param cb */ @POST("/user/register-username") - void registerUserEmailPass(@Body Map body, Callback> cb); + Call registerUserEmailPass(@Body Map body); /** * Method for sending a register request using the Twitter auth provider * @param body - * @param cb */ @POST("/user/register-twitter") - void registerUserTwitter(@Body Map body, Callback> cb); + Call registerUserTwitter(@Body Map body); /** * Refresh the current JWT token - * @param cb */ @GET("/user/refresh_token") - void refreshToken(Callback cb); + Call refreshToken(); /** * Method for sending a login request using the Facebook auth provider * @param body - * @param cb */ @POST("/user/login-facebook") - void loginFacebook(@Body Map body, Callback cb); + Call loginFacebook(@Body Map body); /** * Method for sending a login request using the Twitter auth provider * @param body - * @param cb */ @POST("/user/login-twitter") - void loginTwitter(@Body Map body, Callback cb); + Call loginTwitter(@Body Map body); /** * Method for sending a login request using the Email/Password auth provider * @param body - * @param cb */ @POST("/user/login_password") - void loginEmailAndPassword(@Body Map body, Callback cb); + Call loginEmailAndPassword(@Body Map body); /** * Method for sending a logout request - * @param cb */ @GET("/user/logout") - void logout(Callback> cb); + Call logout(); /** * Method for requesting a password reset email * @param body - * @param cb */ @POST("/user/request_password_reset") - void requestPasswordReset(@Body Map body, Callback> cb); + Call requestPasswordReset(@Body Map body); /** * Method for changing a user authentication password * @param body - * @param cb */ @POST("/user/password_reset") - void resetPassword(@Body Map body, Callback> cb); + Call resetPassword(@Body Map body); @POST("/user/update") - void updateUser(@Body Map body, Callback> cb); + Call updateUser(@Body Map body); @GET("/user/metadata") - void getUserMetadata(Callback cb); + Call getUserMetadata(); @POST("/user/update_metadata") - void updateUserMetadata(@Body Map body, Callback> cb); + Call updateUserMetadata(@Body Map body); /** * Method for sending a subscribe request * @param body - * @param cb */ @POST("/object/subscribe") - void subscribe(@Body Map body, Callback> cb); + Call subscribe(@Body Map body); @POST("/object/count") - void count(@Body Map body, Callback cb); + Call count(@Body Map body); /** * Method for sending an unsubscribe request * @param body - * @param cb */ @POST("/object/unsubscribe") - void unsubscribe(@Body Map body, Callback> cb); + Call unsubscribe(@Body Map body); /** * Method for sending an object creation request * @param body - * @param cb */ @POST("/object/create") - void create(@Body Map body, Callback> cb); + Call create(@Body Map body); /** * Method for sending an object update request * @param body - * @param cb */ @POST("/object/update") - void update(@Body Map body, Callback> cb); + Call update(@Body Map body); /** * Method for sending an object delete request * @param body - * @param cb */ @POST("/object/delete") - void delete(@Body Map body, Callback> cb); + Call delete(@Body Map body); @POST("/proxy") - void proxy(@Body TelepatProxyRequest request, Callback cb); + Call proxy(@Body TelepatProxyRequest request); @GET("/user/me") - void me(Callback cb); + Call me(); @GET("/user/get") - void get(@Query("user_id") String userId, Callback cb); + Call get(@Query("user_id") String userId); @POST("/email") - void sendEmail(@Body Map body, Callback cb); + Call sendEmail(@Body Map body); @POST("/til/append") - void appendToIndexedList(@Body Map body, Callback cb); + Call appendToIndexedList(@Body Map body); @POST("/til/get") - void checkIndexedListMembers(@Body Map body, Callback cb); + Call checkIndexedListMembers(@Body Map body); @POST("/til/removeList") - void deleteIndexedList(@Body Map body, Callback cb); + Call deleteIndexedList(@Body Map body); @POST("/til/removeMember") - void removeFromIndexedList(@Body Map body, Callback cb); + Call removeFromIndexedList(@Body Map body); } diff --git a/src/main/java/io/telepat/sdk/networking/OctopusRequestInterceptor.java b/src/main/java/io/telepat/sdk/networking/OctopusRequestInterceptor.java index d532518..141ad14 100644 --- a/src/main/java/io/telepat/sdk/networking/OctopusRequestInterceptor.java +++ b/src/main/java/io/telepat/sdk/networking/OctopusRequestInterceptor.java @@ -1,15 +1,19 @@ package io.telepat.sdk.networking; +import java.io.IOException; + import io.telepat.sdk.Telepat; import io.telepat.sdk.utilities.TelepatConstants; import io.telepat.sdk.utilities.TelepatUtilities; -import retrofit.RequestInterceptor; +import okhttp3.Interceptor; +import okhttp3.Request; +import okhttp3.Response; /** * Created by Andrei Marinescu on 02.06.2015. * Retrofit RequestInterceptor implementation for adding required HTTP headers */ -public class OctopusRequestInterceptor implements RequestInterceptor{ +public class OctopusRequestInterceptor implements Interceptor { /** * The Telepat application ID */ @@ -55,18 +59,6 @@ public OctopusRequestInterceptor(String apiKey, String appId) { } - @Override - public void intercept(RequestFacade request) { - request.addHeader("Content-Type", "application/json"); - if(apiKeyHash!=null) { request.addHeader("X-BLGREQ-SIGN", apiKeyHash); } - if(appId!=null) { request.addHeader("X-BLGREQ-APPID", appId); } - if(udid!=null) { request.addHeader("X-BLGREQ-UDID", udid); } - else { request.addHeader("X-BLGREQ-UDID",""); } - if(authorizationToken!=null) { - request.addHeader("Authorization","Bearer "+authorizationToken); - } - } - public String getAppId() { return appId; } @@ -98,4 +90,33 @@ public String getAuthorizationToken() { public void setAuthorizationToken(String authorizationToken) { this.authorizationToken = authorizationToken; } + + @Override + public Response intercept(Chain chain) throws IOException { + Request request = chain.request(); + + Request.Builder builder = request.newBuilder(); + builder.addHeader("Content-Type", "application/json"); + + if (apiKeyHash != null) { + builder.addHeader("X-BLGREQ-SIGN", apiKeyHash); + } + if (appId != null) { + builder.addHeader("X-BLGREQ-APPID", appId); + } + if (udid != null) { + builder.addHeader("X-BLGREQ-UDID", udid); + } else { + builder.addHeader("X-BLGREQ-UDID", ""); + } + if (authorizationToken != null) { + builder.addHeader("Authorization", "Bearer " + authorizationToken); + } + + request = builder.build(); + + return chain.proceed(request); + + + } } diff --git a/src/main/java/io/telepat/sdk/networking/responses/ApiError.java b/src/main/java/io/telepat/sdk/networking/responses/ApiError.java new file mode 100644 index 0000000..e3eb99b --- /dev/null +++ b/src/main/java/io/telepat/sdk/networking/responses/ApiError.java @@ -0,0 +1,47 @@ +package io.telepat.sdk.networking.responses; + +import java.io.IOException; +import java.lang.annotation.Annotation; + +import io.telepat.sdk.Telepat; +import okhttp3.ResponseBody; +import retrofit2.Converter; +import retrofit2.Response; + +/** + * Created by ovidiuluca on 14/10/2016. + */ + +public class ApiError { + + private int status; + private String message; + private String code; + + public int status() { + return status; + } + + public String message() { + return message; + } + + public String code(){ + return code; + } + + + public static ApiError parseError(Response response) { + Converter converter = Telepat.getInstance().retrofit.responseBodyConverter(ApiError.class, new Annotation[0]); + + ApiError error; + + try { + error = converter.convert(response.errorBody()); + } catch (IOException e) { + return new ApiError(); + } + + return error; + } +} diff --git a/src/main/java/io/telepat/sdk/networking/responses/GenericApiResponse.java b/src/main/java/io/telepat/sdk/networking/responses/GenericApiResponse.java index ca12c0a..f348377 100644 --- a/src/main/java/io/telepat/sdk/networking/responses/GenericApiResponse.java +++ b/src/main/java/io/telepat/sdk/networking/responses/GenericApiResponse.java @@ -1,6 +1,17 @@ package io.telepat.sdk.networking.responses; +import android.util.Log; + +import com.google.gson.JsonElement; +import com.google.gson.annotations.SerializedName; + +import org.json.JSONException; +import org.json.JSONObject; + import java.util.HashMap; +import java.util.Iterator; + +import static io.telepat.sdk.utilities.TelepatConstants.TAG; /** * Created by Andrei Marinescu on 03.06.2015. @@ -8,5 +19,29 @@ */ public class GenericApiResponse { public int status; - public HashMap content; + @SerializedName("content") + public JsonElement content; + + public HashMap getContent() { + + HashMap map = new HashMap<>(); + JSONObject jObject = null; + try { + jObject = new JSONObject(content.toString()); + + Iterator keys = jObject.keys(); + + while( keys.hasNext() ){ + String key = (String)keys.next(); + String value = jObject.getString(key); + map.put(key, value); + + } + } catch (JSONException e) { + e.printStackTrace(); + } + + + return map; + } } diff --git a/src/main/java/io/telepat/sdk/networking/responses/TelepatCountCallback.java b/src/main/java/io/telepat/sdk/networking/responses/TelepatCountCallback.java index 1972fdb..aa1cccd 100644 --- a/src/main/java/io/telepat/sdk/networking/responses/TelepatCountCallback.java +++ b/src/main/java/io/telepat/sdk/networking/responses/TelepatCountCallback.java @@ -1,6 +1,5 @@ package io.telepat.sdk.networking.responses; -import retrofit.RetrofitError; /** * Created by Andrei Marinescu on 11/29/15. @@ -8,5 +7,5 @@ */ public interface TelepatCountCallback { void onSuccess(int number, Double aggregationResult); - void onFailure(RetrofitError error); + void onFailure(String error); } diff --git a/src/main/java/io/telepat/sdk/networking/transports/gcm/GcmBroadcastReceiver.java b/src/main/java/io/telepat/sdk/networking/transports/gcm/GcmBroadcastReceiver.java deleted file mode 100644 index 9885edb..0000000 --- a/src/main/java/io/telepat/sdk/networking/transports/gcm/GcmBroadcastReceiver.java +++ /dev/null @@ -1,34 +0,0 @@ -package io.telepat.sdk.networking.transports.gcm; - -import android.app.Activity; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.support.v4.content.WakefulBroadcastReceiver; -import android.util.Log; - -import com.google.android.gms.gcm.GoogleCloudMessaging; - -import io.telepat.sdk.utilities.TelepatConstants; - -/** - * Created by catalinivan, Andrei Marinescu on 09/03/15. - * GCM Receiver class. - */ -public class GcmBroadcastReceiver extends WakefulBroadcastReceiver -{ - @Override - public void onReceive(Context context, Intent intent) - { - GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(context); - Log.d(TelepatConstants.TAG, "Message received with message type = " + gcm.getMessageType(intent) + " and content = " + intent.getExtras().toString()); - // Explicitly specify that GcmIntentService will handle the intent. - ComponentName comp = new ComponentName(context.getPackageName(), GcmIntentService.class.getName()); - // Start the service, keeping the device awake while it is launching. - startWakefulService(context, (intent.setComponent(comp))); - setResultCode(Activity.RESULT_OK); - } - - - -} diff --git a/src/main/java/io/telepat/sdk/networking/transports/gcm/GcmIntentService.java b/src/main/java/io/telepat/sdk/networking/transports/gcm/GcmIntentService.java deleted file mode 100644 index e97f3aa..0000000 --- a/src/main/java/io/telepat/sdk/networking/transports/gcm/GcmIntentService.java +++ /dev/null @@ -1,92 +0,0 @@ -package io.telepat.sdk.networking.transports.gcm; - -import android.app.IntentService; -import android.content.Intent; - -import com.google.gson.Gson; -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; - -import io.telepat.sdk.Telepat; -import io.telepat.sdk.models.Channel; -import io.telepat.sdk.models.TransportNotification; -import io.telepat.sdk.utilities.TelepatLogger; - -/** - * Created by catalinivan, Andrei Marinescu on 09/03/15. - * GCM message handler - */ -public class GcmIntentService extends IntentService -{ - private static final String SERVICE_NAME = "io.telepat.sdk.networking.transports.gcm.GcmIntentService"; - - /** - * Reference to a Gson instance, used for notification Json decoding - */ - private final Gson jsonParser = new Gson(); - - public GcmIntentService() - { - super(SERVICE_NAME); - } - - @Override - protected void onHandleIntent(Intent intent) { - if(intent.getStringExtra("data") != null) { - TelepatLogger.log("we have data"); - String data = intent.getStringExtra("data"); - JsonObject jsonObject = jsonParser.fromJson(data, JsonObject.class); - JsonArray newObjects = (JsonArray) jsonObject.get("new"); - JsonArray updatedObjects = (JsonArray) jsonObject.get("updated"); - JsonArray deletedObjects = (JsonArray) jsonObject.get("deleted"); - if(newObjects != null) prepareChannelNotification(newObjects, Channel.NotificationType.ObjectAdded); - if(updatedObjects != null) prepareChannelNotification(updatedObjects, Channel.NotificationType.ObjectUpdated); - if(deletedObjects != null) prepareChannelNotification(deletedObjects, Channel.NotificationType.ObjectDeleted); - } - } - - /** - * Builds TransportNotification objects and relays it to the relevant channels - * @param objects A JsonArray of notifications - * @param notificationType The type of notifications (added/updated/deleted) - */ - private void prepareChannelNotification(JsonArray objects, Channel.NotificationType notificationType) { - for(JsonElement notificationElement : objects) { - if(notificationElement.isJsonObject()) { - JsonObject notificationObject = (JsonObject) notificationElement; - TransportNotification notification = new TransportNotification(notificationObject, notificationType); - if(notificationObject.has("subscription")) { - String channelIdentifier = notificationObject.get("subscription").getAsString(); - notifyChannel(channelIdentifier, notification); - } else { - TelepatLogger.log("V2 notification format detected"); - if(notificationObject.has("subscriptions")) { - JsonArray affectedChannels = notificationObject.getAsJsonArray("subscriptions"); - for(JsonElement element : affectedChannels) { - if(element.isJsonPrimitive()) { - String channelIdentifier = element.getAsString(); - notifyChannel(channelIdentifier, notification); - } - } - } - } - } - } - } - - private void notifyChannel(String channelIdentifier, TransportNotification notification) { - if (channelIdentifier.endsWith(":context")) { - Telepat.getInstance().fireContextUpdate(notification); - } else { - Channel channel = Telepat.getInstance().getSubscribedChannel(channelIdentifier); - if (channel != null) channel.processNotification(notification); - else { - TelepatLogger.error("No local channel instance available"); - channel = new Channel(channelIdentifier); - channel.processNotification(notification); - } - } - } - -} diff --git a/src/main/java/io/telepat/sdk/networking/transports/gcm/GcmRegistrar.java b/src/main/java/io/telepat/sdk/networking/transports/gcm/GcmRegistrar.java deleted file mode 100644 index 1d63295..0000000 --- a/src/main/java/io/telepat/sdk/networking/transports/gcm/GcmRegistrar.java +++ /dev/null @@ -1,153 +0,0 @@ -package io.telepat.sdk.networking.transports.gcm; - -import android.content.Context; -import android.os.AsyncTask; -import android.text.TextUtils; -import android.util.Log; - -import com.google.android.gms.common.ConnectionResult; -import com.google.android.gms.common.GooglePlayServicesUtil; -import com.google.android.gms.gcm.GoogleCloudMessaging; - -import java.io.IOException; -import java.util.Random; - -import io.telepat.sdk.Telepat; -import io.telepat.sdk.utilities.TelepatConstants; -import io.telepat.sdk.utilities.TelepatLogger; -import io.telepat.sdk.utilities.TelepatUtilities; - -/** - * Created by Andrei Marinescu on 03.06.2015. - * GCM Token Registration - */ -public class GcmRegistrar { - public static final String PROPERTY_REG_ID = "registration_id"; - private static final String PROPERTY_APP_VERSION = "appVersion"; - private static final int MAX_ATTEMPTS = 3; - private Context mContext; - - public GcmRegistrar(Context mContext) { - this.mContext = mContext; - } - - public void initGcmRegistration() { - if (checkPlayServices()) - { - String regId = getRegistrationId(); - - if (TextUtils.isEmpty(regId)) - { - gcmRegisterAsync(); - } - else - { - Telepat.getInstance().registerDevice(regId, false); - } - } - } - - private void gcmRegisterAsync() { - new AsyncTask() - { - @Override - protected Object doInBackground(Object[] params) - { - long backoff = 2000 + new Random().nextInt(1000); - GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(mContext); - for (int i = 0; i < MAX_ATTEMPTS; i++) - { - try - { - String regId = gcm.register(TelepatConstants.GCM_SENDER_ID); - TelepatLogger.log(regId); - - storeRegistrationId(regId); - Telepat.getInstance().registerDevice(regId, true); - - return regId; - } - catch (IOException e) - { - e.printStackTrace(); - TelepatLogger.error(e.getMessage()); - - if (i == MAX_ATTEMPTS - 1) { - break; - } - - try { - TelepatLogger.log("Sleeping for " + backoff + " ms before retry"); - Thread.sleep(backoff); - } - catch (InterruptedException e1) { - // Activity finished before we complete - exit. - TelepatLogger.log("Thread interrupted: abort remaining retries!"); - Thread.currentThread().interrupt(); - return ""; - } - // increase backoff exponentially - backoff *= 2; - } - } - - return null; - } - }.execute(null, null, null); - } - - /** - * Retrieve the GCM registration ID from internal storage. - * @return The registration ID if found, or an empty string if the app was updated - * or no registration ID. - */ - private String getRegistrationId() { - String registrationId = (String) Telepat.getInstance() - .getDBInstance() - .getOperationsData(PROPERTY_REG_ID, "", String.class); - - if (registrationId.isEmpty()) { - Log.i(TelepatConstants.TAG, "Registration not found."); - return ""; - } - // Check if app was updated; if so, it must clear the registration ID - // since the existing registration ID is not guaranteed to work with - // the new app version. - int registeredVersion = (int) Telepat.getInstance() - .getDBInstance() - .getOperationsData(PROPERTY_APP_VERSION, Integer.MIN_VALUE, Integer.class); - int currentVersion = TelepatUtilities.getAppVersion(mContext); - if (registeredVersion != currentVersion) { - Log.i(TelepatConstants.TAG, "App version changed."); - return ""; - } - - Log.d(TelepatConstants.TAG, "Registration id is: " + registrationId); - return registrationId; - } - - /** - * Stores the registration ID and app versionCode in the application's - * - * @param regId registration ID - */ - private void storeRegistrationId(String regId) - { - int appVersion = TelepatUtilities.getAppVersion(mContext); - Log.i(TelepatConstants.TAG, "Saving regId on app version " + appVersion); - Telepat.getInstance().getDBInstance().setOperationsData(PROPERTY_REG_ID, regId); - Telepat.getInstance().getDBInstance().setOperationsData(PROPERTY_APP_VERSION, appVersion); - } - - /** - * Check the device to make sure it has the Google Play Services APK. If - * it doesn't, display a dialog that allows users to download the APK from - * the Google Play Store or enable it in the device's system settings. - */ - private boolean checkPlayServices() - { - int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable( - mContext.getApplicationContext()); - return resultCode == ConnectionResult.SUCCESS; - } -} diff --git a/src/main/java/io/telepat/sdk/networking/transports/gcm/TelepatFirebaseInstanceIDService.java b/src/main/java/io/telepat/sdk/networking/transports/gcm/TelepatFirebaseInstanceIDService.java new file mode 100644 index 0000000..7b83453 --- /dev/null +++ b/src/main/java/io/telepat/sdk/networking/transports/gcm/TelepatFirebaseInstanceIDService.java @@ -0,0 +1,50 @@ +package io.telepat.sdk.networking.transports.gcm; + +import android.util.Log; + +import com.google.firebase.iid.FirebaseInstanceId; +import com.google.firebase.iid.FirebaseInstanceIdService; + +import io.telepat.sdk.Telepat; +import io.telepat.sdk.utilities.TelepatConstants; +import io.telepat.sdk.utilities.TelepatLogger; +import io.telepat.sdk.utilities.TelepatUtilities; + + +/** + * Created by ovidiuluca on 01/11/2016. + */ + +public class TelepatFirebaseInstanceIDService extends FirebaseInstanceIdService { + + private static final String PROPERTY_APP_VERSION = "appVersion"; + public static final String PROPERTY_REG_ID = "registration_id"; + + /** + * Called if InstanceID token is updated. This may occur if the security of + * the previous token had been compromised. Note that this is called when the InstanceID token + * is initially generated so this is where you would retrieve the token. + */ + // [START refresh_token] + @Override + public void onTokenRefresh() { + String refreshedToken = FirebaseInstanceId.getInstance().getToken(); + TelepatLogger.log("FCM Registration token is: " + refreshedToken); + + storeRegistrationId(refreshedToken); + Telepat.getInstance().registerDevice(refreshedToken, true); + } + + /** + * Stores the registration ID and app versionCode in the application's + * + * @param regId registration ID + */ + private void storeRegistrationId(String regId) { + int appVersion = TelepatUtilities.getAppVersion(this); + Log.i(TelepatConstants.TAG, "Saving regId on app version " + appVersion); + Telepat.getInstance().getDBInstance().setOperationsData(PROPERTY_REG_ID, regId); + Telepat.getInstance().getDBInstance().setOperationsData(PROPERTY_APP_VERSION, appVersion); + } + +} diff --git a/src/main/java/io/telepat/sdk/networking/transports/gcm/TelepatFirebaseMessagingService.java b/src/main/java/io/telepat/sdk/networking/transports/gcm/TelepatFirebaseMessagingService.java new file mode 100644 index 0000000..b0c8216 --- /dev/null +++ b/src/main/java/io/telepat/sdk/networking/transports/gcm/TelepatFirebaseMessagingService.java @@ -0,0 +1,87 @@ +package io.telepat.sdk.networking.transports.gcm; + +import com.google.firebase.messaging.FirebaseMessagingService; +import com.google.firebase.messaging.RemoteMessage; +import com.google.gson.Gson; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; + +import io.telepat.sdk.Telepat; +import io.telepat.sdk.models.Channel; +import io.telepat.sdk.models.TransportNotification; +import io.telepat.sdk.utilities.TelepatLogger; + +/** + * Created by ovidiuluca on 01/11/2016. + * + */ + +public class TelepatFirebaseMessagingService extends FirebaseMessagingService { + private final Gson jsonParser = new Gson(); + @Override + public void onMessageReceived(RemoteMessage remoteMessage) { + TelepatLogger.log("Received message is: " + remoteMessage.getData().get("data")); + if (remoteMessage.getData() != null && remoteMessage.getData().size() > 0) { + JsonObject jsonObject = jsonParser.fromJson(remoteMessage.getData().get("data"), JsonObject.class); + try { + JsonArray newObjects = (JsonArray) jsonObject.get("new"); + JsonArray updatedObjects = (JsonArray) jsonObject.get("updated"); + JsonArray deletedObjects = (JsonArray) jsonObject.get("deleted"); + if (newObjects != null) + prepareChannelNotification(newObjects, Channel.NotificationType.ObjectAdded); + if (updatedObjects != null) + prepareChannelNotification(updatedObjects, Channel.NotificationType.ObjectUpdated); + if (deletedObjects != null) + prepareChannelNotification(deletedObjects, Channel.NotificationType.ObjectDeleted); + } catch (NullPointerException ex) { + ex.printStackTrace(); + } + } + + } + + /** + * Builds TransportNotification objects and relays it to the relevant channels + * + * @param objects A JsonArray of notifications + * @param notificationType The type of notifications (added/updated/deleted) + */ + private void prepareChannelNotification(JsonArray objects, Channel.NotificationType notificationType) { + for (JsonElement notificationElement : objects) { + if (notificationElement.isJsonObject()) { + JsonObject notificationObject = (JsonObject) notificationElement; + TransportNotification notification = new TransportNotification(notificationObject, notificationType); + if (notificationObject.has("subscription")) { + String channelIdentifier = notificationObject.get("subscription").getAsString(); + notifyChannel(channelIdentifier, notification); + } else { + TelepatLogger.log("V2 notification format detected"); + if (notificationObject.has("subscriptions")) { + JsonArray affectedChannels = notificationObject.getAsJsonArray("subscriptions"); + for (JsonElement element : affectedChannels) { + if (element.isJsonPrimitive()) { + String channelIdentifier = element.getAsString(); + notifyChannel(channelIdentifier, notification); + } + } + } + } + } + } + } + + private void notifyChannel(String channelIdentifier, TransportNotification notification) { + if (channelIdentifier.endsWith(":context")) { + Telepat.getInstance().fireContextUpdate(notification); + } else { + Channel channel = Telepat.getInstance().getSubscribedChannel(channelIdentifier); + if (channel != null) channel.processNotification(notification); + else { + TelepatLogger.error("No local channel instance available"); + channel = new Channel(channelIdentifier); + channel.processNotification(notification); + } + } + } +} diff --git a/src/main/java/io/telepat/sdk/utilities/TelepatConstants.java b/src/main/java/io/telepat/sdk/utilities/TelepatConstants.java index 6b60dea..6bd80ae 100644 --- a/src/main/java/io/telepat/sdk/utilities/TelepatConstants.java +++ b/src/main/java/io/telepat/sdk/utilities/TelepatConstants.java @@ -21,6 +21,8 @@ public final class TelepatConstants public static String GCM_SENDER_ID = "361851333269"; + public static final String CODE_TOKEN_EXPIRED = "046"; + private TelepatConstants() { } }