Skip to content
This repository has been archived by the owner on Jul 18, 2021. It is now read-only.

Commit

Permalink
[#6] Fix async plug-in settings
Browse files Browse the repository at this point in the history
  • Loading branch information
ccjernigan committed Jan 30, 2016
1 parent b958cc6 commit 017adde
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 12 deletions.
5 changes: 3 additions & 2 deletions README.md
Expand Up @@ -27,7 +27,7 @@ The build.gradle repositories section would look something like the following:
And the dependencies section would look something like this:

dependencies {
compile group:'com.twofortyfouram', name:'android-plugin-client-sdk-for-locale', version:'[4.0.1, 5.0['
compile group:'com.twofortyfouram', name:'android-plugin-client-sdk-for-locale', version:'[4.0.2, 5.0['
}


Expand Down Expand Up @@ -115,4 +115,5 @@ At runtime the host launches the plug-in's Activity, the plug-in's Activity retu
* Remove AbstractLocalePluginActivity and AbstractLocaleFragmentPluginActivity. These deprecated Activities implemented UI logic, while this SDK should only responsible for communicating with the host.
* Rename AbstractPluginConditionReceiver.getPluginConditionState(Context, Bundle) to be more internally consistent.
* 4.0.0: Remove strings and resources that were previously used by AbstractLocalePluginActivity and AbstractLocaleFragmentPluginActivity.
* 4.0.1: Fix visibility of Activity onPostCreate(). Thanks @ddykhoff for reporting this issue!
* 4.0.1: Fix visibility of Activity onPostCreate(). Thanks @ddykhoff for reporting this issue!
* 4.0.2: Fix async plug-in settings. Thanks @giech for reporting this issue!
2 changes: 1 addition & 1 deletion gradle.properties
Expand Up @@ -5,7 +5,7 @@ ANDROID_TARGET_SDK_VERSION=23
ANDROID_COMPILE_SDK_VERSION=23

ANDROID_VERSION_CODE=5
ANDROID_VERSION_NAME=4.0.1
ANDROID_VERSION_NAME=4.0.2

// Toggle predexing. Should be disabled for CI.
IS_PREDEXING_ENABLED=true
Expand Down
Expand Up @@ -25,16 +25,18 @@
import android.support.annotation.NonNull;
import android.util.Pair;

import com.twofortyfouram.spackle.AndroidSdkVersion;
import com.twofortyfouram.spackle.ThreadUtil;
import com.twofortyfouram.spackle.ThreadUtil.ThreadPriority;

import net.jcip.annotations.ThreadSafe;

import static com.twofortyfouram.assertion.Assertions.assertInRangeInclusive;
import static com.twofortyfouram.assertion.Assertions.assertNotNull;

/**
* Simplifies asynchronous broadcast handling. Subclasses call
* {@link #goAsyncWithCallback(AsyncCallback)}, and the abstract class takes
* {@link #goAsyncWithCallback(AsyncCallback, boolean)}, and the abstract class takes
* care of executing the callback on a background thread.
*/
@ThreadSafe
Expand All @@ -43,9 +45,13 @@
/*
* This method is package visible rather than protected so that it will be
* obfuscated by ProGuard.
*
* @param callback Callback to execute on a background thread.
* @param isOrdered Indicates whether an ordered broadcast is being processed.
*/
@TargetApi(VERSION_CODES.HONEYCOMB)
/* package */ final void goAsyncWithCallback(@NonNull final AsyncCallback callback) {
/* package */ final void goAsyncWithCallback(@NonNull final AsyncCallback callback,
final boolean isOrdered) {
assertNotNull(callback, "callback"); //$NON-NLS-1$

final PendingResult pendingResult = goAsync();
Expand All @@ -59,13 +65,25 @@
ThreadPriority.BACKGROUND);
final Handler handler = new Handler(thread.getLooper(), handlerCallback);

handler.sendMessage(handler.obtainMessage(AsyncHandlerCallback.MESSAGE_HANDLE_CALLBACK,
new Pair<PendingResult, AsyncCallback>(pendingResult, callback)));
final Object obj = new Pair<PendingResult, AsyncCallback>(pendingResult, callback);
final int isOrderedInt = isOrdered ? 1 : 0;
final Message msg = handler
.obtainMessage(AsyncHandlerCallback.MESSAGE_HANDLE_CALLBACK, isOrderedInt, 0, obj);

final boolean isMessageSent = handler.sendMessage(msg);
if (!isMessageSent) {
throw new AssertionError();
}
}

@TargetApi(VERSION_CODES.HONEYCOMB)
private static final class AsyncHandlerCallback implements Handler.Callback {

/**
* Message MUST contain a {@code Pair<PendingResult, AsyncCallback>} as the {@code msg.obj}
* and a boolean encoded in the {@code msg.arg1} to indicate whether the broadcast was
* ordered.
*/
public static final int MESSAGE_HANDLE_CALLBACK = 0;

@Override
Expand All @@ -74,31 +92,50 @@ public boolean handleMessage(final Message msg) {
switch (msg.what) {
case MESSAGE_HANDLE_CALLBACK: {
assertNotNull(msg.obj, "msg.obj"); //$NON-NLS-1$
assertInRangeInclusive(msg.arg1, 0, 1, "msg.arg1"); //$NON-NLS-1$

final Pair<PendingResult, AsyncCallback> pair = castObj(msg.obj);
final boolean isOrdered = 0 != msg.arg1;

final PendingResult pendingResult = pair.first;
final AsyncCallback asyncCallback = pair.second;

try {
pendingResult.setResultCode(asyncCallback.runAsync());
final int resultCode = asyncCallback.runAsync();

if (isOrdered) {
pendingResult.setResultCode(resultCode);
}
} finally {
pendingResult.finish();
}

Looper.myLooper().quit();
quit();

break;
}
}
return false;
return true;
}

@NonNull
@SuppressWarnings("unchecked")
private static Pair<PendingResult, AsyncCallback> castObj(@NonNull final Object o) {
return (Pair<PendingResult, AsyncCallback>) o;
}

private static void quit() {
if (AndroidSdkVersion.isAtLeastSdk(VERSION_CODES.JELLY_BEAN_MR2)) {
quitJellybeanMr2();
} else {
Looper.myLooper().quit();
}
}

@TargetApi(VERSION_CODES.JELLY_BEAN_MR2)
private static void quitJellybeanMr2() {
Looper.myLooper().quitSafely();
}
}

/* package */static interface AsyncCallback {
Expand Down
Expand Up @@ -141,7 +141,7 @@ public int runAsync() {

};

goAsyncWithCallback(callback);
goAsyncWithCallback(callback, isOrderedBroadcast());
} else {
final int pluginState = getPluginConditionResult(context, bundle);
assertResult(pluginState);
Expand Down
Expand Up @@ -131,7 +131,7 @@ public int runAsync() {

};

goAsyncWithCallback(callback);
goAsyncWithCallback(callback, isOrderedBroadcast());
} else {
firePluginSetting(context, bundle);
}
Expand Down

0 comments on commit 017adde

Please sign in to comment.