1616package org .androidannotations .helper ;
1717
1818import static com .sun .codemodel .JExpr ._new ;
19- import static com .sun .codemodel .JExpr ._super ;
19+ import static com .sun .codemodel .JExpr .ref ;
2020import static com .sun .codemodel .JMod .PRIVATE ;
2121import static com .sun .codemodel .JMod .PUBLIC ;
2222import static com .sun .codemodel .JMod .STATIC ;
2323
24+ import java .util .List ;
25+
26+ import javax .lang .model .element .Element ;
27+ import javax .lang .model .element .ElementKind ;
28+ import javax .lang .model .element .ExecutableElement ;
29+ import javax .lang .model .element .TypeElement ;
30+ import javax .lang .model .element .VariableElement ;
31+
2432import org .androidannotations .holder .HasIntentBuilder ;
2533
2634import com .sun .codemodel .JBlock ;
2937import com .sun .codemodel .JConditional ;
3038import com .sun .codemodel .JExpr ;
3139import com .sun .codemodel .JExpression ;
40+ import com .sun .codemodel .JFieldRef ;
3241import com .sun .codemodel .JFieldVar ;
42+ import com .sun .codemodel .JInvocation ;
3343import com .sun .codemodel .JMethod ;
3444import com .sun .codemodel .JMod ;
3545import com .sun .codemodel .JVar ;
@@ -38,16 +48,23 @@ public class ActivityIntentBuilder extends IntentBuilder {
3848
3949 private static final int MIN_SDK_WITH_FRAGMENT_SUPPORT = 11 ;
4050
51+ private static final int MIN_SDK_WITH_ACTIVITY_OPTIONS = 16 ;
52+
4153 private JFieldVar fragmentField ;
4254 private JFieldVar fragmentSupportField ;
4355
56+ private JFieldRef optionsField ;
57+
4458 public ActivityIntentBuilder (HasIntentBuilder holder , AndroidManifest androidManifest ) {
4559 super (holder , androidManifest );
4660 }
4761
4862 @ Override
4963 public void build () throws JClassAlreadyExistsException {
5064 super .build ();
65+
66+ optionsField = ref ("lastOptions" );
67+
5168 createAdditionalConstructor (); // See issue #541
5269 createAdditionalIntentMethods ();
5370 overrideStartForResultMethod ();
@@ -97,9 +114,6 @@ private JFieldVar addFragmentConstructor(JClass fragmentClass, String fieldName)
97114 }
98115
99116 private void overrideStartForResultMethod () {
100- if (fragmentSupportField == null && fragmentField == null ) {
101- return ;
102- }
103117 JMethod method = holder .getIntentBuilderClass ().method (PUBLIC , holder .codeModel ().VOID , "startForResult" );
104118 method .annotate (Override .class );
105119 JVar requestCode = method .param (holder .codeModel ().INT , "requestCode" );
@@ -117,10 +131,73 @@ private void overrideStartForResultMethod() {
117131 } else {
118132 condition = condition ._elseif (fragmentField .ne (JExpr ._null ()));
119133 }
120- condition ._then () //
134+
135+ JBlock fragmentStartForResultInvocationBlock ;
136+
137+ if (hasActivityOptionsInFragment () && shouldGuardActivityOptions ()) {
138+ fragmentStartForResultInvocationBlock = createCallWithIfGuard (requestCode , condition ._then (), fragmentField );
139+ } else {
140+ fragmentStartForResultInvocationBlock = condition ._then ();
141+ }
142+ JInvocation invocation = fragmentStartForResultInvocationBlock //
121143 .invoke (fragmentField , "startActivityForResult" ).arg (intentField ).arg (requestCode );
144+ if (hasActivityOptionsInFragment ()) {
145+ invocation .arg (optionsField );
146+ }
147+ }
148+
149+ JBlock activityStartInvocationBlock = null ;
150+
151+ if (condition != null ) {
152+ activityStartInvocationBlock = condition ._else ();
153+ } else {
154+ activityStartInvocationBlock = method .body ();
155+ }
156+
157+ JConditional activityCondition = activityStartInvocationBlock ._if (contextField ._instanceof (holder .classes ().ACTIVITY ));
158+ JBlock thenBlock = activityCondition ._then ();
159+ JVar activityVar = thenBlock .decl (holder .classes ().ACTIVITY , "activity" , JExpr .cast (holder .classes ().ACTIVITY , contextField ));
160+
161+ if (hasActivityCompatInClasspath () && hasActivityOptionsInActivityCompat ()) {
162+ thenBlock .staticInvoke (holder .classes ().ACTIVITY_COMPAT , "startActivityForResult" ) //
163+ .arg (activityVar ).arg (intentField ).arg (requestCode ).arg (optionsField );
164+ } else if (hasActivityOptionsInFragment ()) {
165+ JBlock startForResultInvocationBlock ;
166+ if (shouldGuardActivityOptions ()) {
167+ startForResultInvocationBlock = createCallWithIfGuard (requestCode , thenBlock , activityVar );
168+ } else {
169+ startForResultInvocationBlock = thenBlock ;
170+ }
171+
172+ startForResultInvocationBlock .invoke (activityVar , "startActivityForResult" ) //
173+ .arg (intentField ).arg (requestCode ).arg (optionsField );
174+ } else {
175+ thenBlock .invoke (activityVar , "startActivityForResult" ).arg (intentField ).arg (requestCode );
176+ }
177+
178+ if (hasActivityOptionsInFragment ()) {
179+ JBlock startInvocationBlock ;
180+ if (shouldGuardActivityOptions ()) {
181+ startInvocationBlock = createCallWithIfGuard (null , activityCondition ._else (), contextField );
182+ } else {
183+ startInvocationBlock = activityCondition ._else ();
184+ }
185+ startInvocationBlock .invoke (contextField , "startActivity" ).arg (intentField ).arg (optionsField );
186+ } else {
187+ activityCondition ._else ().invoke (contextField , "startActivity" ).arg (intentField );
188+ }
189+ }
190+
191+ private JBlock createCallWithIfGuard (JVar requestCode , JBlock thenBlock , JExpression invocationTarget ) {
192+ JConditional guardIf = thenBlock ._if (holder .classes ().BUILD_VERSION .staticRef ("SDK_INT" ).gte (holder .classes ().BUILD_VERSION_CODES .staticRef ("JELLY_BEAN" )));
193+ JBlock startInvocationBlock = guardIf ._then ();
194+ String methodName = requestCode != null ? "startActivityForResult" : "startActivity" ;
195+
196+ JInvocation invocation = guardIf ._else ().invoke (invocationTarget , methodName ).arg (intentField );
197+ if (requestCode != null ) {
198+ invocation .arg (requestCode );
122199 }
123- condition . _else (). invoke ( _super (), "startForResult" ). arg ( requestCode ) ;
200+ return startInvocationBlock ;
124201 }
125202
126203 protected boolean hasFragmentInClasspath () {
@@ -131,4 +208,50 @@ protected boolean hasFragmentInClasspath() {
131208 protected boolean hasFragmentSupportInClasspath () {
132209 return elementUtils .getTypeElement (CanonicalNameConstants .SUPPORT_V4_FRAGMENT ) != null ;
133210 }
211+
212+ protected boolean hasActivityCompatInClasspath () {
213+ return elementUtils .getTypeElement (CanonicalNameConstants .ACTIVITY_COMPAT ) != null ;
214+ }
215+
216+ protected boolean hasActivityOptionsInFragment () {
217+ if (!hasFragmentInClasspath ()) {
218+ return false ;
219+ }
220+
221+ TypeElement fragment = elementUtils .getTypeElement (CanonicalNameConstants .FRAGMENT );
222+
223+ return hasActivityOptions (fragment , 1 );
224+ }
225+
226+ protected boolean hasActivityOptionsInActivityCompat () {
227+ TypeElement activityCompat = elementUtils .getTypeElement (CanonicalNameConstants .ACTIVITY_COMPAT );
228+
229+ return hasActivityOptions (activityCompat , 2 );
230+ }
231+
232+ private boolean hasActivityOptions (TypeElement type , int optionsParamPosition ) {
233+ if (type == null ) {
234+ return false ;
235+ }
236+
237+ for (Element element : type .getEnclosedElements ()) {
238+ if (element .getKind () == ElementKind .METHOD ) {
239+ ExecutableElement executableElement = (ExecutableElement ) element ;
240+ if (executableElement .getSimpleName ().contentEquals ("startActivity" )) {
241+ List <? extends VariableElement > parameters = executableElement .getParameters ();
242+ if (parameters .size () == optionsParamPosition + 1 ) {
243+ VariableElement parameter = parameters .get (optionsParamPosition );
244+ if (parameter .asType ().toString ().equals (CanonicalNameConstants .BUNDLE )) {
245+ return true ;
246+ }
247+ }
248+ }
249+ }
250+ }
251+ return false ;
252+ }
253+
254+ protected boolean shouldGuardActivityOptions () {
255+ return androidManifest .getMinSdkVersion () < MIN_SDK_WITH_ACTIVITY_OPTIONS ;
256+ }
134257}
0 commit comments