Skip to content

Commit 297e649

Browse files
Feature/androido (#153)
* Android O solution.... to start. Need to replace the scheduler with job service instead of alarm service. * use job scheduler instead of alarm service for android o * update for android o. set the context via ContextWrapper and cleanup tests to run on android o as well as other platforms. * make sure to use logger and update proguard rules
1 parent f309aeb commit 297e649

File tree

20 files changed

+513
-93
lines changed

20 files changed

+513
-93
lines changed

.travis.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,10 @@ android:
33
components:
44
- tools
55
- platform-tools
6-
- build-tools-25.0.2
7-
- android-24
6+
- tools
87
- doc-24
98
- extra-android-m2repository
10-
- sys-img-armeabi-v7a-android-24
9+
- sys-img-armeabi-v7a-android-22
1110
jdk:
1211
- oraclejdk8
1312
before_cache:
@@ -19,7 +18,8 @@ cache:
1918
before_script:
2019
- echo $TRAVIS_BRANCH
2120
- echo $TRAVIS_TAG
22-
- echo no | android create avd --force -n test -t android-24 --abi default/armeabi-v7a
21+
- android list targets
22+
- echo no | android create avd --force -n test -t android-22 --abi armeabi-v7a
2323
- emulator -avd test -no-audio -no-window &
2424
- android-wait-for-emulator
2525
- adb shell input keyevent 82 &

android-sdk/src/androidTest/java/com/optimizely/ab/android/sdk/OptimizelyManagerTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,8 +217,8 @@ public void injectOptimizely() {
217217
verify(startListener).onStart(any(OptimizelyClient.class));
218218
}
219219

220-
@RequiresApi(api = Build.VERSION_CODES.HONEYCOMB)
221220
@Test
221+
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
222222
public void injectOptimizelyNullListener() {
223223
Context context = mock(Context.class);
224224
PackageManager packageManager = mock(PackageManager.class);

android-sdk/src/main/java/com/optimizely/ab/android/sdk/OptimizelyManager.java

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,14 @@ void setOptimizelyStartListener(@Nullable OptimizelyStartListener optimizelyStar
111111
this.optimizelyStartListener = optimizelyStartListener;
112112
}
113113

114+
private void notifyStartListener() {
115+
if (optimizelyStartListener != null) {
116+
optimizelyStartListener.onStart(getOptimizely());
117+
optimizelyStartListener = null;
118+
}
119+
120+
}
121+
114122
/**
115123
* Initialize Optimizely Synchronously
116124
* <p>
@@ -232,16 +240,13 @@ public void onDatafileLoaded(@Nullable String datafile) {
232240
// We should always call the callback even with the dummy
233241
// instances. Devs might gate the rest of their app
234242
// based on the loading of Optimizely
235-
OptimizelyStartListener optimizelyStartListener = getOptimizelyStartListener();
236-
if (optimizelyStartListener != null) {
237-
optimizelyStartListener.onStart(getOptimizely());
238-
}
243+
notifyStartListener();
239244
}
240245
}
241246

242247
@Override
243248
public void onStop(Context context) {
244-
stop(context);
249+
245250
}
246251
};
247252
}
@@ -345,7 +350,7 @@ void injectOptimizely(@NonNull final Context context, final @NonNull UserProfile
345350
public void onStartComplete(UserProfileService userProfileService) {
346351
if (optimizelyStartListener != null) {
347352
logger.info("Sending Optimizely instance to listener");
348-
optimizelyStartListener.onStart(optimizelyClient);
353+
notifyStartListener();
349354
} else {
350355
logger.info("No listener to send Optimizely to");
351356
}
@@ -355,7 +360,7 @@ public void onStartComplete(UserProfileService userProfileService) {
355360
else {
356361
if (optimizelyStartListener != null) {
357362
logger.info("Sending Optimizely instance to listener");
358-
optimizelyStartListener.onStart(optimizelyClient);
363+
notifyStartListener();
359364
} else {
360365
logger.info("No listener to send Optimizely to");
361366
}
@@ -364,7 +369,7 @@ public void onStartComplete(UserProfileService userProfileService) {
364369
logger.error("Unable to build OptimizelyClient instance", e);
365370
if (optimizelyStartListener != null) {
366371
logger.info("Sending Optimizely instance to listener may be null on failure");
367-
optimizelyStartListener.onStart(optimizelyClient);
372+
notifyStartListener();
368373
}
369374
} catch (Error e) {
370375
logger.error("Unable to build OptimizelyClient instance", e);

build.gradle

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,10 @@ allprojects {
4747
}
4848

4949
ext {
50-
compile_sdk_version = 24
51-
build_tools_version = "25.0.2"
50+
compile_sdk_version = 26
51+
build_tools_version = "26.0.1"
5252
min_sdk_version = 10
53-
target_sdk_version = 24
53+
target_sdk_version = 26
5454

5555
java_core_ver = "1.8.0"
5656
android_logger_ver = "1.3.6"

datafile-handler/src/androidTest/java/com/optimizely/ab/android/datafile_handler/DatafileLoaderTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ public class DatafileLoaderTest {
6363
private Client client;
6464
private Logger logger;
6565
private DatafileLoadedListener datafileLoadedListener;
66+
Context context = InstrumentationRegistry.getTargetContext();
6667

6768
@Before
6869
public void setup() {

datafile-handler/src/main/java/com/optimizely/ab/android/datafile_handler/DatafileRescheduler.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,19 @@
1616

1717
package com.optimizely.ab.android.datafile_handler;
1818

19+
import android.app.job.JobInfo;
20+
import android.app.job.JobScheduler;
21+
import android.app.job.JobWorkItem;
1922
import android.content.BroadcastReceiver;
23+
import android.content.ComponentName;
2024
import android.content.Context;
2125
import android.content.Intent;
26+
import android.os.Build;
2227
import android.support.annotation.NonNull;
2328

2429
import com.optimizely.ab.android.shared.Cache;
30+
import com.optimizely.ab.android.shared.JobWorkService;
31+
import com.optimizely.ab.android.shared.ServiceScheduler;
2532

2633
import org.slf4j.Logger;
2734
import org.slf4j.LoggerFactory;
@@ -91,7 +98,7 @@ void dispatch(Intent intent) {
9198
List<String> projectIds = backgroundWatchersCache.getWatchingProjectIds();
9299
for (String projectId : projectIds) {
93100
intent.putExtra(DatafileService.EXTRA_PROJECT_ID, projectId);
94-
context.startService(intent);
101+
ServiceScheduler.startService(context, DatafileService.JOB_ID, intent);
95102

96103
logger.info("Rescheduled data file watching for project {}", projectId);
97104
}

datafile-handler/src/main/java/com/optimizely/ab/android/datafile_handler/DatafileService.java

Lines changed: 37 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,19 @@
1717
package com.optimizely.ab.android.datafile_handler;
1818

1919
import android.app.Service;
20+
import android.content.Context;
2021
import android.content.Intent;
2122
import android.os.Binder;
2223
import android.os.Build;
2324
import android.os.IBinder;
2425
import android.support.annotation.NonNull;
26+
import android.support.annotation.Nullable;
2527
import android.support.annotation.RequiresApi;
2628

2729
import com.optimizely.ab.android.shared.Cache;
2830
import com.optimizely.ab.android.shared.Client;
2931
import com.optimizely.ab.android.shared.OptlyStorage;
32+
import com.optimizely.ab.android.shared.JobWorkScheduledService;
3033

3134
import org.slf4j.Logger;
3235
import org.slf4j.LoggerFactory;
@@ -38,13 +41,14 @@
3841
* These services will only be used if you are using our {@link DefaultDatafileHandler}.
3942
* You can chose to implement your own handler and use all or part of this package.
4043
*/
41-
public class DatafileService extends Service {
44+
public class DatafileService extends Service implements JobWorkScheduledService {
4245
/**
4346
* Extra containing the project id this instance of Optimizely was built with
4447
*/
4548
public static final String EXTRA_PROJECT_ID = "com.optimizely.ab.android.EXTRA_PROJECT_ID";
4649
public static final String FORMAT_VERSIONED_CDN_URL = "https://cdn.optimizely.com/public/%s/datafile_v%s.json";
4750
static final String DATAFILE_VERSION = "3";
51+
public static final Integer JOB_ID = 2113;
4852

4953
@NonNull private final IBinder binder = new LocalBinder();
5054
Logger logger = LoggerFactory.getLogger(DatafileService.class);
@@ -57,26 +61,7 @@ public class DatafileService extends Service {
5761
@RequiresApi(api = Build.VERSION_CODES.HONEYCOMB)
5862
@Override
5963
public int onStartCommand(Intent intent, int flags, int startId) {
60-
if (intent != null) {
61-
if (intent.hasExtra(EXTRA_PROJECT_ID)) {
62-
String projectId = intent.getStringExtra(EXTRA_PROJECT_ID);
63-
DatafileClient datafileClient = new DatafileClient(
64-
new Client(new OptlyStorage(getApplicationContext()), LoggerFactory.getLogger(OptlyStorage.class)),
65-
LoggerFactory.getLogger(DatafileClient.class));
66-
DatafileCache datafileCache = new DatafileCache(
67-
projectId,
68-
new Cache(getApplicationContext(), LoggerFactory.getLogger(Cache.class)),
69-
LoggerFactory.getLogger(DatafileCache.class));
70-
71-
String datafileUrl = getDatafileUrl(projectId);
72-
DatafileLoader datafileLoader = new DatafileLoader(this, datafileClient, datafileCache, Executors.newSingleThreadExecutor(), LoggerFactory.getLogger(DatafileLoader.class));
73-
datafileLoader.getDatafile(datafileUrl, null);
74-
} else {
75-
logger.warn("Data file service received an intent with no project id extra");
76-
}
77-
} else {
78-
logger.warn("Data file service received a null intent");
79-
}
64+
onWork(intent);
8065
return super.onStartCommand(intent, flags, startId);
8166
}
8267

@@ -119,6 +104,37 @@ public void getDatafile(String projectId, DatafileLoader datafileLoader, Datafil
119104
datafileLoader.getDatafile(datafileUrl, loadedListener);
120105
}
121106

107+
@Override
108+
public void initialize() {
109+
110+
}
111+
112+
@RequiresApi(api = Build.VERSION_CODES.HONEYCOMB)
113+
@Override
114+
public void onWork(@Nullable Intent intent) {
115+
if (intent != null) {
116+
if (intent.hasExtra(EXTRA_PROJECT_ID)) {
117+
String projectId = intent.getStringExtra(EXTRA_PROJECT_ID);
118+
DatafileClient datafileClient = new DatafileClient(
119+
new Client(new OptlyStorage(this.getApplicationContext()), LoggerFactory.getLogger(OptlyStorage.class)),
120+
LoggerFactory.getLogger(DatafileClient.class));
121+
DatafileCache datafileCache = new DatafileCache(
122+
projectId,
123+
new Cache(this.getApplicationContext(), LoggerFactory.getLogger(Cache.class)),
124+
LoggerFactory.getLogger(DatafileCache.class));
125+
126+
String datafileUrl = getDatafileUrl(projectId);
127+
DatafileLoader datafileLoader = new DatafileLoader(this, datafileClient, datafileCache, Executors.newSingleThreadExecutor(), LoggerFactory.getLogger(DatafileLoader.class));
128+
datafileLoader.getDatafile(datafileUrl, null);
129+
} else {
130+
logger.warn("Data file service received an intent with no project id extra");
131+
}
132+
} else {
133+
logger.warn("Data file service received a null intent");
134+
}
135+
136+
}
137+
122138
public class LocalBinder extends Binder {
123139
public DatafileService getService() {
124140
// Return this instance of LocalService so clients can call public methods

datafile-handler/src/main/java/com/optimizely/ab/android/datafile_handler/DatafileServiceConnection.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,13 +74,13 @@ public void onServiceConnected(ComponentName className,
7474
final DatafileService datafileService = binder.getService();
7575
if (datafileService != null) {
7676
DatafileClient datafileClient = new DatafileClient(
77-
new Client(new OptlyStorage(datafileService.getApplicationContext()),
77+
new Client(new OptlyStorage(context.getApplicationContext()),
7878
LoggerFactory.getLogger(OptlyStorage.class)),
7979
LoggerFactory.getLogger(DatafileClient.class));
8080

8181
DatafileCache datafileCache = new DatafileCache(
8282
projectId,
83-
new Cache(datafileService.getApplicationContext(), LoggerFactory.getLogger(Cache.class)),
83+
new Cache(context.getApplicationContext(), LoggerFactory.getLogger(Cache.class)),
8484
LoggerFactory.getLogger(DatafileCache.class));
8585

8686
DatafileLoader datafileLoader = new DatafileLoader(datafileService,

datafile-handler/src/main/java/com/optimizely/ab/android/datafile_handler/DefaultDatafileHandler.java

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -108,11 +108,9 @@ public void onStop(Context context) {
108108
public void startBackgroundUpdates(Context context, String projectId, Long updateInterval) {
109109
enableBackgroundCache(context, projectId);
110110

111-
AlarmManager alarmManager = (AlarmManager) context
112-
.getSystemService(Context.ALARM_SERVICE);
113111
ServiceScheduler.PendingIntentFactory pendingIntentFactory = new ServiceScheduler
114112
.PendingIntentFactory(context.getApplicationContext());
115-
ServiceScheduler serviceScheduler = new ServiceScheduler(alarmManager, pendingIntentFactory,
113+
ServiceScheduler serviceScheduler = new ServiceScheduler(context, pendingIntentFactory,
116114
LoggerFactory.getLogger(ServiceScheduler.class));
117115

118116
Intent intent = new Intent(context.getApplicationContext(), DatafileService.class);
@@ -127,11 +125,9 @@ public void startBackgroundUpdates(Context context, String projectId, Long updat
127125
* @param projectId project id of the datafile uploading
128126
*/
129127
public void stopBackgroundUpdates(Context context, String projectId) {
130-
AlarmManager alarmManager = (AlarmManager) context
131-
.getSystemService(Context.ALARM_SERVICE);
132128
ServiceScheduler.PendingIntentFactory pendingIntentFactory = new ServiceScheduler
133129
.PendingIntentFactory(context.getApplicationContext());
134-
ServiceScheduler serviceScheduler = new ServiceScheduler(alarmManager, pendingIntentFactory,
130+
ServiceScheduler serviceScheduler = new ServiceScheduler(context, pendingIntentFactory,
135131
LoggerFactory.getLogger(ServiceScheduler.class));
136132
Intent intent = new Intent(context.getApplicationContext(), DatafileService.class);
137133
serviceScheduler.unschedule(intent);

0 commit comments

Comments
 (0)