Skip to content

Commit

Permalink
close some url connections and streams. add connectivity change to te… (
Browse files Browse the repository at this point in the history
#133)

* close some url connections and streams. add connectivity change to test-app manifest.  add a few more exception handlers.

* changed reschedulers to wake on wifi state change : connecting

* fixup docs and cleanup

* cleanup from mike's comments

* update changelog
  • Loading branch information
thomaszurkan-optimizely authored Jul 27, 2017
1 parent e4f2802 commit 186c0c8
Show file tree
Hide file tree
Showing 20 changed files with 272 additions and 60 deletions.
23 changes: 23 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,27 @@
# Optimizely Android X SDK Changelog
### 1.4.0-alpha-RC1
July 26, 2017

- Release candidate for 1.4.0

*Bug Fixes*

- Better javadocs.
- Cleanup any resource leaks.
- Better exception handling to avoid any crashes.
- Fix proguard rules
- Fix logger issue
- Allow EventRescheduler to work with wifi change intent filter (you don't have to include that intent filter).

*Breaking Changes*

- Must include intent filter for EventRescheduler and DatafileRescheduler in the application manifest if the developer wants to use them (see the test-app manifest for an example).
- Pass context into OptimizelyManager.Builder.
- UserProfileService added.
- Background processes are not running by default.
- Various handlers (EventHandler, DatafileHandler, ErrorHandler) can be overridden.


### 1.4.0-alpha
July 11, 2017

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public class OptimizelyClient {
private final Logger logger;

@Nullable private Optimizely optimizely;
@Nullable private Map<String, String> defaultAttributes;
@NonNull private Map<String, String> defaultAttributes;

OptimizelyClient(@Nullable Optimizely optimizely, @NonNull Logger logger) {
this.optimizely = optimizely;
Expand Down Expand Up @@ -86,7 +86,7 @@ protected void setDefaultAttributes(@NonNull Map<String, String> attrs) {
* @return a new map of both the default attributes and attributes passed in.
*/
private Map<String, String> getAllAttributes(@NonNull Map<String, String> attrs) {
Map<String,String> combinedMap = new HashMap<String,String>(defaultAttributes);
Map<String,String> combinedMap = new HashMap<>(defaultAttributes);

// this essentially overrides defaultAttributes if the attrs passed in have the same key.
combinedMap.putAll(attrs);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ static Map<String, String> buildDefaultAttributesMap(Context context, Logger log
}


Map<String, String> attrMap = new HashMap<String, String>();
Map<String, String> attrMap = new HashMap<>();

attrMap.put(DEVICE_MODEL_KEY, androidDeviceModel);
attrMap.put(SDK_VERSION_KEY, androidSdkVersionName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ public class OptimizelyManager {
LoggerFactory.getLogger(OptimizelyClient.class));

@NonNull private DatafileHandler datafileHandler;
@NonNull private final long datafileDownloadInterval;
@NonNull private final long eventDispatchInterval;
private final long datafileDownloadInterval;
private final long eventDispatchInterval;
@Nullable private EventHandler eventHandler = null;
@NonNull private ErrorHandler errorHandler;
@NonNull private Logger logger;
Expand Down Expand Up @@ -323,6 +323,7 @@ public String getProjectId() {
return projectId;
}

@NonNull
public DatafileHandler getDatafileHandler() {
return datafileHandler;
}
Expand Down Expand Up @@ -390,6 +391,7 @@ private OptimizelyClient buildOptimizely(@NonNull Context context, @NonNull Stri
return new OptimizelyClient(optimizely, LoggerFactory.getLogger(OptimizelyClient.class));
}

@NonNull
@VisibleForTesting
public UserProfileService getUserProfileService() {
return userProfileService;
Expand Down
3 changes: 2 additions & 1 deletion datafile-handler/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@
</service>
<!--
Add these lines to your manifest if you want the services to schedule themselves again after a boot
or package replace.
or package replace. Without these lines in your application manifest, the DatafileRescheduler will not be used.
See {link test_app} AndroidManifest.xml as an example.
<receiver
android:name="DatafileRescheduler"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package com.optimizely.ab.android.datafile_handler;

import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;

Expand All @@ -31,17 +32,33 @@

/**
* Caches a json dict that saves state about which project IDs have background watching enabled.
* This is used by the rescheduler to determine if backgrounding was on for a project id. If backgrounding is on,
* then when the device is restarted or the app is reinstalled, the rescheduler will kick in and reschedule the datafile background
* download. In order to use this the rescheduler needs to be included in the application manifest.
* Calling {@link DatafileHandler#stopBackgroundUpdates(Context, String)} sets this background cache to false.
*/
class BackgroundWatchersCache {
static final String BACKGROUND_WATCHERS_FILE_NAME = "optly-background-watchers.json";
@NonNull private final Cache cache;
@NonNull private final Logger logger;

/**
* Create BackgroundWatchersCache Object.
*
* @param cache object for caching project id and whether watched or not.
* @param logger the logger to log errors and warnings.
*/
BackgroundWatchersCache(@NonNull Cache cache, @NonNull Logger logger) {
this.cache = cache;
this.logger = logger;
}

/**
* Set the watching flag for the proejct id.
* @param projectId project id to set watching.
* @param watching flag to signify if the project is running in the background.
* @return boolean indicating whether the set succeed or not
*/
boolean setIsWatching(@NonNull String projectId, boolean watching) {
if (projectId.isEmpty()) {
logger.error("Passed in an empty string for projectId");
Expand All @@ -61,6 +78,11 @@ boolean setIsWatching(@NonNull String projectId, boolean watching) {
return false;
}

/**
* Return if the project is set to be watched in the background or not.
* @param projectId project id to test
* @return true if it has backgrounding, false if not.
*/
boolean isWatching(@NonNull String projectId) {
if (projectId.isEmpty()) {
logger.error("Passed in an empty string for projectId");
Expand All @@ -81,6 +103,10 @@ boolean isWatching(@NonNull String projectId) {
return false;
}

/**
* Get a list of all project ids that are being watched for backgrounding.
* @return a list of project ids
*/
List<String> getWatchingProjectIds() {
List<String> projectIds = new ArrayList<>();
try {
Expand All @@ -101,6 +127,11 @@ List<String> getWatchingProjectIds() {
return projectIds;
}

/**
* Load the JSONObject from cache
* @return JSONObject if successful. JSONObject can be empty
* @throws JSONException if there was a problem parsing the JSON
*/
@Nullable
private JSONObject load() throws JSONException {
String backGroundWatchersFile = cache.load(BACKGROUND_WATCHERS_FILE_NAME);
Expand All @@ -112,10 +143,19 @@ private JSONObject load() throws JSONException {
return new JSONObject(backGroundWatchersFile);
}

/**
* Delete the background watchers cache file.
* @return true if successful and false if it failed.
*/
protected boolean delete() {
return cache.delete(BACKGROUND_WATCHERS_FILE_NAME);
}

/**
* Save the JSON string to the background cache file.
* @param backgroundWatchersJson JSON string containing projectid and whether watched or not.
* @return true if successful.
*/
private boolean save(String backgroundWatchersJson) {
logger.info("Saving background watchers file {}.", BACKGROUND_WATCHERS_FILE_NAME);
boolean saved = cache.save(BACKGROUND_WATCHERS_FILE_NAME, backgroundWatchersJson);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
import org.slf4j.Logger;

/**
* Abstracts the actual data "file" {@link java.io.File}.
* Abstracts the actual data "file" {@link java.io.File}. to a cached file
*/
public class DatafileCache {

Expand All @@ -37,25 +37,47 @@ public class DatafileCache {
@NonNull private final String filename;
@NonNull private final Logger logger;

/**
* Create a DatafileCache Object
* @param projectId project id for cache
* @param cache shared generic file based {link Cache}
* @param logger logger to use
*/
public DatafileCache(@NonNull String projectId, @NonNull Cache cache, @NonNull Logger logger) {
this.cache = cache;
this.filename = String.format(FILENAME, projectId);
this.logger = logger;
}

/**
* Delete the datafile cache
* @return true if successful
*/
public boolean delete() {
return cache.delete(filename);
}

/**
* Check to see if the datafile cache exists
* @return true if it exists
*/
public boolean exists() {
return cache.exists(filename);
}

/**
* Return the filename to the datafile cache
* @return filename for datafile cache
*/
@VisibleForTesting
public String getFileName() {
return filename;
}

/**
* Loads the datafile from cache into a JSONObject
* @return JSONObject if exists or nulll if it doesn't or there was a problem
*/
@Nullable
public JSONObject load() {
String datafile = cache.load(filename);
Expand All @@ -71,6 +93,11 @@ public JSONObject load() {
}
}

/**
* Save a datafile to cache.
* @param dataFile to write to cache
* @return true if successful.
*/
public boolean save(String dataFile) {
return cache.save(filename, dataFile);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ public class DatafileClient {
@NonNull private final Client client;
@NonNull private final Logger logger;

/**
* Create a DatafileClient Object.
* @param client Shared {@link Client} object
* @param logger logger for logging.
*/
public DatafileClient(@NonNull Client client, @NonNull Logger logger) {
this.client = client;
this.logger = logger;
Expand Down Expand Up @@ -89,7 +94,12 @@ public String execute() {
return null;
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
try {
urlConnection.disconnect();
}
catch (Exception e) {
logger.error("Error closing connection", e);
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,22 @@
/**
* Broadcast Receiver that handles app upgrade and phone restart broadcasts in order
* to reschedule {@link DatafileService}
* In order to use this class you must include the declaration in your AndroidManifest.xml.
* <pre>
* {@code
* <receiver
* android:name="DatafileRescheduler"
* android:enabled="true"
* android:exported="false">
* <intent-filter>
* <action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
* <action android:name="android.intent.action.BOOT_COMPLETED" />
* </intent-filter>
* </receiver>
* }
* </pre>
*
* @hide
* as well as set the download interval for datafile download in the Optimizely builder.
*/
public class DatafileRescheduler extends BroadcastReceiver {
Logger logger = LoggerFactory.getLogger(DatafileRescheduler.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@

/**
* Service that handles loading the datafile from cache or downloads it from the CDN
*
* @hide
* These services will only be used if you are using our {@link DefaultDatafileHandler}.
* You can chose to implement your own handler and use all or part of this package.
*/
public class DatafileService extends Service {
/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@

import java.util.concurrent.Executors;

/**
* The DatafileServiceConnection is used to bind to a DatafileService. The DatafileService does that actual download.
* The Service Connection kicks off the service after being connected. The connection is unbound after a successful download.
*/
public class DatafileServiceConnection implements ServiceConnection {

@NonNull private final Context context;
Expand All @@ -40,14 +44,21 @@ public class DatafileServiceConnection implements ServiceConnection {

private boolean bound = false;

/**
* Create a datafile service connection object.
* @param projectId project id for service
* @param context current application context.
* @param listener listener to call after service download has completed.
*/
public DatafileServiceConnection(@NonNull String projectId, @NonNull Context context, @NonNull DatafileLoadedListener listener) {
this.projectId = projectId;
this.context = context;
this.listener = listener;
}

/**
* @hide
* Get the bound {@link DatafileService} and set it up for download.
*
* @see ServiceConnection#onServiceConnected(ComponentName, IBinder)
*/
@RequiresApi(api = Build.VERSION_CODES.HONEYCOMB)
Expand Down Expand Up @@ -84,7 +95,7 @@ public void onServiceConnected(ComponentName className,
}

/**
* @hide
* Call stop on the listener after the service has been disconnected.
* @see ServiceConnection#onServiceDisconnected(ComponentName)
*/
@Override
Expand All @@ -93,10 +104,18 @@ public void onServiceDisconnected(ComponentName arg0) {
listener.onStop(context);
}

/**
* Is the service bound?
* @return true if it is bound.
*/
public boolean isBound() {
return bound;
}

/**
* Set whether the service is bound or not.
* @param bound boolean flag.
*/
public void setBound(Boolean bound) {
this.bound = bound;
}
Expand Down
Loading

0 comments on commit 186c0c8

Please sign in to comment.