Skip to content
This repository was archived by the owner on Feb 26, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -97,4 +97,27 @@
public enum RegisterAt {
OnCreateOnDestroy, OnStartOnStop, OnResumeOnPause, OnAttachOnDetach
}

/**
* <p>
* Should be used on any native, {@link android.os.Parcelable} or
* {@link java.io.Serializable} parameter of a method annotated with
* {@link ReceiverAction} to inject the extra put in the intent parameter of
* {@code void onReceive(Context context, Intent intent)}. The key of this
* extra is the value of the annotation {@link ReceiverAction.Extra} if it
* is set or the name of the parameter.
* </p>
*/
@Retention(RetentionPolicy.CLASS)
@Target(ElementType.PARAMETER)
public @interface Extra {

/**
* Define the extra's name. If this parameter isn't set the annotated
* parameter name will be used.
*
* @return the extra's name
*/
String value() default "";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ public AnnotationHandlers(ProcessingEnvironment processingEnvironment) {
add(new HttpsClientHandler(processingEnvironment));
add(new HierarchyViewerSupportHandler(processingEnvironment));
add(new WindowFeatureHandler(processingEnvironment));
add(new ReceiverHandler(processingEnvironment));
new ReceiverHandler(processingEnvironment).register(this);
new ReceiverActionHandler(processingEnvironment).register(this);
new OnActivityResultHandler(processingEnvironment).register(this);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,17 @@
*/
package org.androidannotations.handler;

import com.sun.codemodel.JBlock;
import com.sun.codemodel.JClass;
import com.sun.codemodel.JExpression;
import com.sun.codemodel.JFieldVar;
import com.sun.codemodel.JMethod;
import com.sun.codemodel.JVar;
import static com.sun.codemodel.JExpr.lit;
import static com.sun.codemodel.JMod.FINAL;
import static com.sun.codemodel.JMod.PUBLIC;
import static com.sun.codemodel.JMod.STATIC;

import java.lang.annotation.Annotation;

import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.Element;
import javax.lang.model.element.VariableElement;

import org.androidannotations.helper.APTCodeModelHelper;
import org.androidannotations.helper.AnnotationHelper;
import org.androidannotations.helper.BundleHelper;
Expand All @@ -29,15 +34,13 @@
import org.androidannotations.model.AnnotationElements;
import org.androidannotations.process.IsValid;

import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.Element;
import javax.lang.model.element.VariableElement;
import java.lang.annotation.Annotation;

import static com.sun.codemodel.JExpr.lit;
import static com.sun.codemodel.JMod.FINAL;
import static com.sun.codemodel.JMod.PUBLIC;
import static com.sun.codemodel.JMod.STATIC;
import com.sun.codemodel.JBlock;
import com.sun.codemodel.JClass;
import com.sun.codemodel.JDefinedClass;
import com.sun.codemodel.JExpression;
import com.sun.codemodel.JFieldVar;
import com.sun.codemodel.JMethod;
import com.sun.codemodel.JVar;

public abstract class ExtraParameterHandler extends BaseAnnotationHandler<GeneratedClassHolder> {

Expand All @@ -48,7 +51,7 @@ public abstract class ExtraParameterHandler extends BaseAnnotationHandler<Genera
public ExtraParameterHandler(Class<? extends Annotation> targetClass, Class<? extends Annotation> methodAnnotationClass, ProcessingEnvironment processingEnvironment) {
super(targetClass, processingEnvironment);
this.methodAnnotationClass = methodAnnotationClass;
this.annotationHelper = new AnnotationHelper(processingEnv);
annotationHelper = new AnnotationHelper(processingEnv);
}

@Override
Expand All @@ -64,6 +67,10 @@ public void process(Element element, GeneratedClassHolder holder) throws Excepti
}

public JExpression getExtraValue(VariableElement parameter, JVar intent, JVar extras, JBlock block, JMethod annotatedMethod, GeneratedClassHolder holder) {
return getExtraValue(parameter, intent, extras, block, annotatedMethod, holder.getGeneratedClass(), holder);
}

public JExpression getExtraValue(VariableElement parameter, JVar intent, JVar extras, JBlock block, JMethod annotatedMethod, JDefinedClass generatedClass, GeneratedClassHolder holder) {
String parameterName = parameter.getSimpleName().toString();
JClass parameterClass = codeModelHelper.typeMirrorToJClass(parameter.asType(), holder);

Expand All @@ -73,16 +80,16 @@ public JExpression getExtraValue(VariableElement parameter, JVar intent, JVar ex
}

BundleHelper bundleHelper = new BundleHelper(annotationHelper, parameter.asType());
JExpression restoreMethodCall = bundleHelper.getExpressionToRestoreFromIntentOrBundle(parameterClass, intent, extras, getStaticExtraField(holder, extraKey), annotatedMethod);
JExpression restoreMethodCall = bundleHelper.getExpressionToRestoreFromIntentOrBundle(parameterClass, intent, extras, getStaticExtraField(generatedClass, extraKey, holder), annotatedMethod);

return block.decl(parameterClass, parameterName, restoreMethodCall);
}

private JFieldVar getStaticExtraField(GeneratedClassHolder holder, String extraName) {
private JFieldVar getStaticExtraField(JDefinedClass generatedClass, String extraName, GeneratedClassHolder holder) {
String staticFieldName = CaseHelper.camelCaseToUpperSnakeCase(null, extraName, "Extra");
JFieldVar staticExtraField = holder.getGeneratedClass().fields().get(staticFieldName);
JFieldVar staticExtraField = generatedClass.fields().get(staticFieldName);
if (staticExtraField == null) {
staticExtraField = holder.getGeneratedClass().field(PUBLIC | STATIC | FINAL, holder.classes().STRING, staticFieldName, lit(extraName));
staticExtraField = generatedClass.field(PUBLIC | STATIC | FINAL, holder.classes().STRING, staticFieldName, lit(extraName));
}
return staticExtraField;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,26 +15,49 @@
*/
package org.androidannotations.handler;

import com.sun.codemodel.*;
import static com.sun.codemodel.JExpr._new;
import static com.sun.codemodel.JExpr._null;
import static com.sun.codemodel.JMod.FINAL;
import static com.sun.codemodel.JMod.PRIVATE;
import static com.sun.codemodel.JMod.PUBLIC;

import java.util.List;

import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.VariableElement;

import org.androidannotations.annotations.Receiver;
import org.androidannotations.helper.APTCodeModelHelper;
import org.androidannotations.helper.ModelConstants;
import org.androidannotations.holder.HasReceiverRegistration;
import org.androidannotations.model.AnnotationElements;
import org.androidannotations.process.IsValid;

import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;

import static com.sun.codemodel.JExpr._new;
import static com.sun.codemodel.JMod.FINAL;
import static com.sun.codemodel.JMod.PRIVATE;
import static com.sun.codemodel.JMod.PUBLIC;
import com.sun.codemodel.JBlock;
import com.sun.codemodel.JClass;
import com.sun.codemodel.JDefinedClass;
import com.sun.codemodel.JExpression;
import com.sun.codemodel.JFieldVar;
import com.sun.codemodel.JInvocation;
import com.sun.codemodel.JMethod;
import com.sun.codemodel.JOp;
import com.sun.codemodel.JVar;

public class ReceiverHandler extends BaseAnnotationHandler<HasReceiverRegistration> {

private final APTCodeModelHelper codeModelHelper = new APTCodeModelHelper();
private ExtraHandler extraHandler;

public ReceiverHandler(ProcessingEnvironment processingEnvironment) {
super(Receiver.class, processingEnvironment);
extraHandler = new ExtraHandler(processingEnvironment);
}

public void register(AnnotationHandlers annotationHandlers) {
annotationHandlers.add(this);
annotationHandlers.add(extraHandler);
}

@Override
Expand All @@ -45,7 +68,7 @@ protected void validate(Element element, AnnotationElements validatedElements, I

validatorHelper.returnTypeIsVoid((ExecutableElement) element, valid);

validatorHelper.param.zeroOrOneIntentParameter((ExecutableElement) element, valid);
validatorHelper.param.hasNoOtherParameterThanContextOrIntentOrReceiverExtraAnnotated((ExecutableElement) element, valid);

validatorHelper.hasNotMultipleAnnotatedMethodWithSameName(element.getEnclosingElement(), valid, Receiver.class);

Expand All @@ -58,8 +81,7 @@ protected void validate(Element element, AnnotationElements validatedElements, I
public void process(Element element, HasReceiverRegistration holder) throws Exception {

String methodName = element.getSimpleName().toString();
boolean hasIntentParam = !((ExecutableElement) element).getParameters().isEmpty();
String receiverName = methodName+"Receiver"+ ModelConstants.GENERATION_SUFFIX;
String receiverName = methodName + "Receiver" + ModelConstants.GENERATION_SUFFIX;

Receiver annotation = element.getAnnotation(Receiver.class);
String[] actions = annotation.actions();
Expand All @@ -68,43 +90,61 @@ public void process(Element element, HasReceiverRegistration holder) throws Exce
boolean local = annotation.local();

JFieldVar intentFilterField = holder.getIntentFilterField(actions, dataSchemes);
JFieldVar receiverField = createReceiverField(holder, receiverName, methodName, hasIntentParam);
JFieldVar receiverField = createReceiverField(holder, receiverName, methodName, (ExecutableElement) element);
registerAndUnregisterReceiver(holder, registerAt, intentFilterField, receiverField, local);
}

private JFieldVar createReceiverField(HasReceiverRegistration holder, String receiverName, String methodName, boolean hasIntentParam) {
private JFieldVar createReceiverField(HasReceiverRegistration holder, String receiverName, String methodName, ExecutableElement executableElement) {
JDefinedClass anonymousReceiverClass = codeModel().anonymousClass(classes().BROADCAST_RECEIVER);
JMethod onReceiveMethod = anonymousReceiverClass.method(PUBLIC, codeModel().VOID, "onReceive");
onReceiveMethod.param(classes().CONTEXT, "context");
JVar contextVar = onReceiveMethod.param(classes().CONTEXT, "context");
JVar intentVar = onReceiveMethod.param(classes().INTENT, "intent");

JInvocation methodCall = onReceiveMethod.body().invoke(methodName);
if (hasIntentParam) {
methodCall.arg(intentVar);
JBlock body = onReceiveMethod.body();

JExpression receiverRef = holder.getGeneratedClass().staticRef("this");
JInvocation methodCall = receiverRef.invoke(methodName);
JVar extras = null;

List<? extends VariableElement> methodParameters = executableElement.getParameters();
for (VariableElement param : methodParameters) {
JClass extraParamClass = codeModelHelper.typeMirrorToJClass(param.asType(), holder);

if (extraParamClass.equals(classes().CONTEXT)) {
methodCall.arg(contextVar);
} else if (extraParamClass.equals(classes().INTENT)) {
methodCall.arg(intentVar);
} else if (param.getAnnotation(Receiver.Extra.class) != null) {
if (extras == null) {
extras = body.decl(classes().BUNDLE, "extras_", JOp.cond(intentVar.invoke("getExtras").ne(_null()), intentVar.invoke("getExtras"), _new(classes().BUNDLE)));
}
methodCall.arg(extraHandler.getExtraValue(param, intentVar, extras, body, onReceiveMethod, anonymousReceiverClass, holder));
}
}

body.add(methodCall);
JExpression receiverInit = _new(anonymousReceiverClass);
return holder.getGeneratedClass().field(PRIVATE | FINAL, classes().BROADCAST_RECEIVER, receiverName, receiverInit);
}

private void registerAndUnregisterReceiver(HasReceiverRegistration holder, Receiver.RegisterAt registerAt, JFieldVar intentFilterField, JFieldVar receiverField, boolean local) {
JBlock registerBlock = null, unregisterBlock = null;
switch (registerAt) {
case OnCreateOnDestroy:
registerBlock = holder.getOnCreateAfterSuperBlock();
unregisterBlock = holder.getOnDestroyBeforeSuperBlock();
break;
case OnStartOnStop:
registerBlock = holder.getOnStartAfterSuperBlock();
unregisterBlock = holder.getOnStopBeforeSuperBlock();
break;
case OnResumeOnPause:
registerBlock = holder.getOnResumeAfterSuperBlock();
unregisterBlock = holder.getOnPauseBeforeSuperBlock();
break;
case OnAttachOnDetach:
registerBlock = holder.getOnAttachAfterSuperBlock();
unregisterBlock = holder.getOnDetachBeforeSuperBlock();
case OnCreateOnDestroy:
registerBlock = holder.getOnCreateAfterSuperBlock();
unregisterBlock = holder.getOnDestroyBeforeSuperBlock();
break;
case OnStartOnStop:
registerBlock = holder.getOnStartAfterSuperBlock();
unregisterBlock = holder.getOnStopBeforeSuperBlock();
break;
case OnResumeOnPause:
registerBlock = holder.getOnResumeAfterSuperBlock();
unregisterBlock = holder.getOnPauseBeforeSuperBlock();
break;
case OnAttachOnDetach:
registerBlock = holder.getOnAttachAfterSuperBlock();
unregisterBlock = holder.getOnDetachBeforeSuperBlock();
}

JExpression broadcastManager;
Expand All @@ -117,4 +157,16 @@ private void registerAndUnregisterReceiver(HasReceiverRegistration holder, Recei
registerBlock.invoke(broadcastManager, "registerReceiver").arg(receiverField).arg(intentFilterField);
unregisterBlock.invoke(broadcastManager, "unregisterReceiver").arg(receiverField);
}

private static class ExtraHandler extends ExtraParameterHandler {

public ExtraHandler(ProcessingEnvironment processingEnvironment) {
super(Receiver.Extra.class, Receiver.class, processingEnvironment);
}

@Override
public String getAnnotationValue(VariableElement parameter) {
return parameter.getAnnotation(Receiver.Extra.class).value();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,22 @@
*/
package org.androidannotations.helper;

import org.androidannotations.annotations.OnActivityResult;
import org.androidannotations.annotations.ReceiverAction;
import org.androidannotations.process.IsValid;
import static java.util.Arrays.asList;

import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import java.lang.annotation.Annotation;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

import static java.util.Arrays.asList;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;

import org.androidannotations.annotations.OnActivityResult;
import org.androidannotations.annotations.Receiver;
import org.androidannotations.annotations.ReceiverAction;
import org.androidannotations.process.IsValid;

public class ValidatorParameterHelper {

Expand Down Expand Up @@ -183,6 +185,11 @@ private void hasNotOtherParameterThanTypes(String[] typesCanonicalNames, Executa
}
}

public void hasNoOtherParameterThanContextOrIntentOrReceiverExtraAnnotated(ExecutableElement executableElement, IsValid valid) {
String[] types = new String[] { CanonicalNameConstants.CONTEXT, CanonicalNameConstants.INTENT };
hasNotOtherParameterThanTypesOrAnnotatedWith(types, Receiver.Extra.class, executableElement, valid);
}

public void hasNoOtherParameterThanContextOrIntentOrReceiverActionExtraAnnotated(ExecutableElement executableElement, IsValid valid) {
String[] types = new String[] {CanonicalNameConstants.CONTEXT, CanonicalNameConstants.INTENT};
hasNotOtherParameterThanTypesOrAnnotatedWith(types, ReceiverAction.Extra.class, executableElement, valid);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@
*/
package org.androidannotations.test15.receiver;

import org.androidannotations.annotations.EActivity;
import org.androidannotations.annotations.Receiver;

import android.app.Activity;
import android.content.Intent;
import android.net.wifi.WifiManager;

import org.androidannotations.annotations.EActivity;
import org.androidannotations.annotations.Receiver;

@EActivity
public class ActivityWithReceiver extends Activity {

Expand All @@ -31,9 +31,12 @@ public class ActivityWithReceiver extends Activity {
public boolean action1Fired = false;
public boolean action2Fired = false;

public String wifiSsid = null;

@Receiver(actions = WifiManager.NETWORK_STATE_CHANGED_ACTION, registerAt = Receiver.RegisterAt.OnResumeOnPause)
protected void onWifiStateChanged(Intent intent) {
protected void onWifiStateChanged(Intent intent, @Receiver.Extra(WifiManager.EXTRA_BSSID) String ssid) {
wifiChangeIntentReceived = true;
wifiSsid = ssid;
}

@Receiver(actions = WifiManager.NETWORK_STATE_CHANGED_ACTION, registerAt = Receiver.RegisterAt.OnStartOnStop, local = true)
Expand All @@ -46,8 +49,7 @@ protected void onDataSchemeHttp(Intent intent) {
dataSchemeHttpIntentReceived = true;
}

@Receiver(actions = { "org.androidannotations.ACTION_1",
"org.androidannotations.ACTION_2" }, registerAt = Receiver.RegisterAt.OnCreateOnDestroy)
@Receiver(actions = { "org.androidannotations.ACTION_1", "org.androidannotations.ACTION_2" }, registerAt = Receiver.RegisterAt.OnCreateOnDestroy)
protected void onBroadcastWithTwoActions(Intent intent) {
String action = intent.getAction();
if (action.equals("org.androidannotations.ACTION_1")) {
Expand Down
Loading