package com.appboy.ui.actions;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.TaskStackBuilder;
import android.util.Log;
import com.appboy.Constants;
import com.appboy.enums.Channel;
import com.appboy.support.AppboyFileUtils;
import com.appboy.support.AppboyLogger;
import com.appboy.ui.AppboyWebViewActivity;
import com.appboy.ui.support.UriUtils;
import java.util.List;
public class UriAction implements IAction {
private static final String TAG = AppboyLogger.getAppboyLogTag(UriAction.class);
private final Bundle mExtras;
private final Channel mChannel;
private Uri mUri;
private boolean mUseWebView;
UriAction(@NonNull Uri uri, Bundle extras, boolean useWebView, Channel channel) {
mUri = uri;
mExtras = extras;
mUseWebView = useWebView;
mChannel = channel;
}
@Override
public Channel getChannel() {
return mChannel;
}
/**
* Opens the action's Uri properly based on mUseWebView status and channel.
*/
@Override
public void execute(Context context) {
AppboyLogger.d(TAG, "Executing Uri action from channel " + mChannel + ": " + mUri + ". UseWebView: " + mUseWebView);
if (mUseWebView) {
openUriWithWebView(context, mUri, mExtras);
} else {
if (mChannel.equals(Channel.PUSH)) {
openUriWithActionViewFromPush(context, mUri, mExtras);
} else {
openUriWithActionView(context, mUri, mExtras);
}
}
}
public void setUri(@NonNull Uri uri) {
mUri = uri;
}
public void setUseWebView(boolean openInWebView) {
mUseWebView = openInWebView;
}
@NonNull
public Uri getUri() {
return mUri;
}
public boolean getUseWebView() {
return mUseWebView;
}
public Bundle getExtras() {
return mExtras;
}
static void openUriWithWebView(Context context, Uri uri, Bundle extras) {
// If the scheme is not a remote scheme, we open it using an ACTION_VIEW intent.
if (!AppboyFileUtils.REMOTE_SCHEMES.contains(uri.getScheme())) {
Log.d(TAG, "Opening non-remote scheme uri with action_view intent.");
openUriWithActionView(context, uri, extras);
return;
}
try {
Intent intent = new Intent(context, AppboyWebViewActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
if (extras != null) {
intent.putExtras(extras);
}
intent.putExtra(Constants.APPBOY_WEBVIEW_URL_EXTRA, uri.toString());
context.startActivity(intent);
} catch (Exception e) {
AppboyLogger.e(TAG, "Appboy AppboyWebViewActivity not opened successfully.", e);
}
}
/**
* Uses an Intent.ACTION_VIEW intent to open the Uri.
*/
static void openUriWithActionView(Context context, Uri uri, Bundle extras) {
Intent intent = getActionViewIntent(context, uri, extras);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
if (intent.resolveActivity(context.getPackageManager()) != null) {
context.startActivity(intent);
} else {
Log.w(TAG, String.format("Could not find appropriate activity to open for deep link %s.", uri));
}
}
/**
* Uses an Intent.ACTION_VIEW intent to open the Uri and places the main activity of the
* activity on the back stack. Primarily used to open Uris from push.
*/
static void openUriWithActionViewFromPush(Context context, Uri uri, Bundle extras) {
Intent uriIntent = getActionViewIntent(context, uri, extras);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
stackBuilder.addNextIntent(UriUtils.getMainActivityIntent(context, extras));
stackBuilder.addNextIntent(uriIntent);
try {
stackBuilder.startActivities(extras);
} catch (ActivityNotFoundException e) {
Log.w(TAG, String.format("Could not find appropriate activity to open for deep link %s.", uri));
}
}
private static Intent getActionViewIntent(Context context, Uri uri, Bundle extras) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(uri);
if (extras != null) {
intent.putExtras(extras);
}
// If the current app can already handle the intent, default to using it
List<ResolveInfo> resolveInfos = context.getPackageManager().queryIntentActivities(intent, 0);
if (resolveInfos.size() > 1) {
for (ResolveInfo resolveInfo : resolveInfos) {
if (resolveInfo.activityInfo.packageName.equals(context.getPackageName())) {
Log.d(TAG, String.format("Setting deep link activity to %s.", resolveInfo.activityInfo.packageName));
intent.setPackage(resolveInfo.activityInfo.packageName);
break;
}
}
}
return intent;
}
}