-
Notifications
You must be signed in to change notification settings - Fork 405
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement DeepLinkDelegate to handle dispatches instead
Three parts: - Generate DeepLinkDelegate class with its single static `dispatchFrom(Activity)` method. - Slim down the generated DeepLinkDispatchActivity to just use this delegate, and it will only be generated if there's no activity annotated with @DeepLinkActivity - Generate a DeepLinkResult class to use on the fly to return results from `dispatchFrom()` - This is a little wonky because the current Api is just a Java library and not an AAR. Generating it is the only current way to make this class available in generated code.
- Loading branch information
Showing
16 changed files
with
451 additions
and
209 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
279 changes: 205 additions & 74 deletions
279
deeplinkdispatch-processor/src/main/java/com/airbnb/deeplinkdispatch/DeepLinkProcessor.java
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
103 changes: 0 additions & 103 deletions
103
deeplinkdispatch-processor/src/test/resources/DeepLinkActivity.java
This file was deleted.
Oops, something went wrong.
108 changes: 108 additions & 0 deletions
108
deeplinkdispatch-processor/src/test/resources/DeepLinkDelegate.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
package com.airbnb.deeplinkdispatch; | ||
|
||
import android.app.Activity; | ||
import android.content.Context; | ||
import android.content.Intent; | ||
import android.net.Uri; | ||
import android.os.Bundle; | ||
import android.support.v4.content.LocalBroadcastManager; | ||
import android.util.Log; | ||
import java.lang.AssertionError; | ||
import java.lang.NullPointerException; | ||
import java.lang.String; | ||
import java.lang.reflect.InvocationTargetException; | ||
import java.lang.reflect.Method; | ||
import java.util.Map; | ||
|
||
public final class DeepLinkDelegate { | ||
private static final String TAG = DeepLinkDelegate.class.getSimpleName(); | ||
|
||
private DeepLinkDelegate() { | ||
throw new AssertionError("No instances."); | ||
} | ||
|
||
public static com.airbnb.deeplinkdispatch.DeepLinkResult dispatchFrom(Activity activity) { | ||
if (activity == null) { | ||
throw new NullPointerException("activity == null"); | ||
} | ||
Intent sourceIntent = activity.getIntent(); | ||
Uri uri = sourceIntent.getData(); | ||
if (uri == null) { | ||
return createResultAndNotify(activity, false, null, "No Uri in given activity's intent."); | ||
} | ||
DeepLinkLoader loader = new DeepLinkLoader(); | ||
loader.load(); | ||
String uriString = uri.toString(); | ||
DeepLinkEntry entry = loader.parseUri(uriString); | ||
if (entry != null) { | ||
DeepLinkUri deepLinkUri = DeepLinkUri.parse(uriString); | ||
Map<String, String> parameterMap = entry.getParameters(uriString); | ||
for (String queryParameter : deepLinkUri.queryParameterNames()) { | ||
for (String queryParameterValue : deepLinkUri.queryParameterValues(queryParameter)) { | ||
if (parameterMap.containsKey(queryParameter)) { | ||
Log.w(TAG, "Duplicate parameter name in path and query param: " + queryParameter); | ||
} | ||
parameterMap.put(queryParameter, queryParameterValue); | ||
} | ||
} | ||
parameterMap.put(DeepLink.URI, uri.toString()); | ||
try { | ||
Class<?> c = entry.getActivityClass(); | ||
Intent newIntent; | ||
if (entry.getType() == DeepLinkEntry.Type.CLASS) { | ||
newIntent = new Intent(activity, c); | ||
} else { | ||
Method method = c.getMethod(entry.getMethod(), Context.class); | ||
newIntent = (Intent) method.invoke(c, activity); | ||
} | ||
if (sourceIntent.getAction() == null) { | ||
newIntent.setAction(sourceIntent.getAction()); | ||
} | ||
if (sourceIntent.getData() == null) { | ||
newIntent.setData(sourceIntent.getData()); | ||
} | ||
Bundle parameters; | ||
if (sourceIntent.getExtras() != null) { | ||
parameters = new Bundle(sourceIntent.getExtras()); | ||
} else { | ||
parameters = new Bundle(); | ||
} | ||
for (Map.Entry<String, String> parameterEntry : parameterMap.entrySet()) { | ||
parameters.putString(parameterEntry.getKey(), parameterEntry.getValue()); | ||
} | ||
newIntent.putExtras(parameters); | ||
newIntent.putExtra(DeepLink.IS_DEEP_LINK, true); | ||
if (activity.getCallingActivity() != null) { | ||
newIntent.setFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT); | ||
} | ||
activity.startActivity(newIntent); | ||
return createResultAndNotify(activity, true, uri, null); | ||
} catch (NoSuchMethodException exception) { | ||
return createResultAndNotify(activity, false, uri, "Deep link to non-existent method: " + entry.getMethod()); | ||
} catch (IllegalAccessException exception) { | ||
return createResultAndNotify(activity, false, uri, "Could not deep link to method: " + entry.getMethod()); | ||
} catch (InvocationTargetException exception) { | ||
return createResultAndNotify(activity, false, uri, "Could not deep link to method: " + entry.getMethod()); | ||
} | ||
} else { | ||
return createResultAndNotify(activity, false, uri, "No registered entity to handle deep link: " + uri.toString()); | ||
} | ||
} | ||
|
||
private static com.airbnb.deeplinkdispatch.DeepLinkResult createResultAndNotify(Context context, final boolean successful, final Uri uri, final String error) { | ||
com.airbnb.deeplinkdispatch.DeepLinkResult result = new com.airbnb.deeplinkdispatch.DeepLinkResult(successful, uri, error); | ||
notifyListener(context, !successful, uri, error); | ||
return result; | ||
} | ||
|
||
private static void notifyListener(Context context, boolean isError, Uri uri, String errorMessage) { | ||
Intent intent = new Intent(); | ||
intent.setAction(DeepLinkActivity.ACTION); | ||
intent.putExtra(DeepLinkActivity.EXTRA_URI, uri.toString()); | ||
intent.putExtra(DeepLinkActivity.EXTRA_SUCCESSFUL, !isError); | ||
if (isError) { | ||
intent.putExtra(DeepLinkActivity.EXTRA_ERROR_MESSAGE, errorMessage); | ||
} | ||
LocalBroadcastManager.getInstance(context).sendBroadcast(intent); | ||
} | ||
} |
13 changes: 13 additions & 0 deletions
13
deeplinkdispatch-processor/src/test/resources/DeepLinkDispatchActivity.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package com.airbnb.deeplinkdispatch; | ||
|
||
import android.app.Activity; | ||
import android.os.Bundle; | ||
import java.lang.Override; | ||
|
||
public class DeepLinkDispatchActivity extends Activity { | ||
@Override | ||
protected void onCreate(Bundle savedInstanceState) { | ||
super.onCreate(savedInstanceState); | ||
DeepLinkDelegate.dispatchFrom(this); | ||
} | ||
} |
68 changes: 68 additions & 0 deletions
68
deeplinkdispatch-processor/src/test/resources/DeepLinkResult.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
package com.airbnb.deeplinkdispatch; | ||
|
||
import android.net.Uri; | ||
import java.lang.Object; | ||
import java.lang.Override; | ||
import java.lang.String; | ||
|
||
public final class DeepLinkResult { | ||
private final boolean successful; | ||
|
||
private final Uri uri; | ||
|
||
private final String errorMessage; | ||
|
||
DeepLinkResult(boolean successful, Uri uri, String errorMessage) { | ||
this.successful = successful; | ||
this.uri = uri; | ||
this.errorMessage = errorMessage; | ||
} | ||
|
||
/** | ||
* @return whether or not the dispatch was a success. | ||
*/ | ||
public boolean isSuccessful() { | ||
return successful; | ||
} | ||
|
||
/** | ||
* @return this result's uri, or {@code null} if there is none. | ||
*/ | ||
public Uri uri() { | ||
return uri; | ||
} | ||
|
||
/** | ||
* @return this result's error message, or {@code null} if there is none. | ||
*/ | ||
public String errorMessage() { | ||
return errorMessage; | ||
} | ||
|
||
@Override | ||
public boolean equals(Object o) { | ||
if (this == o) { return true; } | ||
if (o == null || getClass() != o.getClass()) { return false; } | ||
|
||
DeepLinkResult that = (DeepLinkResult) o; | ||
|
||
if (successful != that.successful) { return false; } | ||
if (uri != null ? !uri.equals(that.uri) : that.uri != null) { return false; } | ||
return errorMessage != null ? errorMessage.equals(that.errorMessage) : that.errorMessage == null;} | ||
|
||
@Override | ||
public int hashCode() { | ||
int result = (successful ? 1 : 0); | ||
result = 31 * result + (uri != null ? uri.hashCode() : 0); | ||
result = 31 * result + (errorMessage != null ? errorMessage.hashCode() : 0); | ||
return result; | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return "DeepLinkResult{" + | ||
"successful=" + successful + | ||
", uri=" + uri + | ||
", errorMessage='" + errorMessage + '\'' + | ||
'}';} | ||
} |
34 changes: 34 additions & 0 deletions
34
deeplinkdispatch/src/main/java/com/airbnb/deeplinkdispatch/DeepLinkActivity.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
/* | ||
* Copyright (C) 2015 Airbnb, Inc. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package com.airbnb.deeplinkdispatch; | ||
|
||
import java.lang.annotation.ElementType; | ||
import java.lang.annotation.Retention; | ||
import java.lang.annotation.RetentionPolicy; | ||
import java.lang.annotation.Target; | ||
|
||
/** | ||
* Indicates that this activity will receive deep links, so the processor knows not to generate | ||
* a separate activity. | ||
*/ | ||
@Target({ ElementType.TYPE }) | ||
@Retention(RetentionPolicy.CLASS) | ||
public @interface DeepLinkActivity { | ||
String ACTION = "com.airbnb.deeplinkdispatch.DEEPLINK_ACTION"; | ||
String EXTRA_SUCCESSFUL = "com.airbnb.deeplinkdispatch.EXTRA_SUCCESSFUL"; | ||
String EXTRA_URI = "com.airbnb.deeplinkdispatch.EXTRA_URI"; | ||
String EXTRA_ERROR_MESSAGE = "com.airbnb.deeplinkdispatch.EXTRA_ERROR_MESSAGE"; | ||
} |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
#Wed Apr 10 15:27:10 PDT 2013 | ||
#Tue Mar 22 02:29:21 PDT 2016 | ||
distributionBase=GRADLE_USER_HOME | ||
distributionPath=wrapper/dists | ||
zipStoreBase=GRADLE_USER_HOME | ||
zipStorePath=wrapper/dists | ||
distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip | ||
distributionUrl=https\://services.gradle.org/distributions/gradle-2.12-all.zip |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.