Index: customtabs/src/android/support/customtabs/browseractions/BrowserActionsIntent.java |
diff --git a/customtabs/src/android/support/customtabs/browseractions/BrowserActionsIntent.java b/customtabs/src/android/support/customtabs/browseractions/BrowserActionsIntent.java |
index aea63b5b0e8eb22c07e4072dfa76afe9edce49f2..663c19580a6fb36b87e3e6c144178e804738510c 100644 |
--- a/customtabs/src/android/support/customtabs/browseractions/BrowserActionsIntent.java |
+++ b/customtabs/src/android/support/customtabs/browseractions/BrowserActionsIntent.java |
@@ -20,14 +20,17 @@ import android.content.Context; |
import android.content.Intent; |
import android.content.pm.PackageManager; |
import android.content.pm.ResolveInfo; |
+import android.graphics.Bitmap; |
import android.net.Uri; |
import android.os.Build; |
import android.os.Bundle; |
import android.support.annotation.IntDef; |
import android.support.annotation.NonNull; |
+import android.support.customtabs.CustomTabsClient; |
import android.support.customtabs.CustomTabsIntent; |
import android.support.customtabs.CustomTabsSession; |
import android.support.v4.content.ContextCompat; |
+import android.util.Log; |
import java.lang.annotation.Retention; |
import java.lang.annotation.RetentionPolicy; |
@@ -42,6 +45,7 @@ import java.util.List; |
* You are strongly encouraged to use {@link BrowserActionsIntent.Builder}.</p> |
*/ |
public class BrowserActionsIntent { |
+ private final static String TAG = "BrowserActions"; |
private final static String TEST_URL = "https://www.example.com"; |
/** |
@@ -83,6 +87,13 @@ public class BrowserActionsIntent { |
public static final String EXTRA_MENU_ITEMS = |
"android.support.customtabs.browseractions.extra.MENU_ITEMS"; |
+ /** |
+ * Extra that specifies the PendingIntent to be launched when a browser specified menu item is |
+ * selected. The id of the chosen item will be notified through the data of its Intent. |
+ */ |
+ public static final String EXTRA_SELECTED_ACTION_PENDING_INTENT = |
+ "android.support.customtabs.browseractions.extra.SELECTED_ACTION_PENDING_INTENT"; |
+ |
/** |
* The maximum allowed number of custom items. |
*/ |
@@ -102,10 +113,25 @@ public class BrowserActionsIntent { |
public static final int URL_TYPE_FILE = 4; |
public static final int URL_TYPE_PLUGIN = 5; |
+ /** |
+ * Defines the the ids of the browser specified menu items in Browser Actions. |
+ * TODO(ltian): A long term solution need, since other providers might have customized menus. |
+ */ |
+ @IntDef({ITEM_INVALID_ITEM, ITEM_OPEN_IN_NEW_TAB, ITEM_OPEN_IN_INCOGNITO, ITEM_DOWNLOAD, |
+ ITEM_COPY, ITEM_SHARE}) |
+ @Retention(RetentionPolicy.SOURCE) |
+ public @interface BrowserActionsItemId {} |
+ public static final int ITEM_INVALID_ITEM = -1; |
+ public static final int ITEM_OPEN_IN_NEW_TAB = 0; |
+ public static final int ITEM_OPEN_IN_INCOGNITO = 1; |
+ public static final int ITEM_DOWNLOAD = 2; |
+ public static final int ITEM_COPY = 3; |
+ public static final int ITEM_SHARE = 4; |
+ |
/** |
* An {@link Intent} used to start the Browser Actions Activity. |
*/ |
- private final Intent mIntent; |
+ public final Intent mIntent; |
/** |
* Gets the Intent of {@link BrowserActionsIntent}. |
@@ -129,6 +155,7 @@ public class BrowserActionsIntent { |
@BrowserActionsUrlType |
private int mType; |
private ArrayList<Bundle> mMenuItems = null; |
+ private PendingIntent mOnItemSelectedPendingIntent = null; |
/** |
* Constructs a {@link BrowserActionsIntent.Builder} object associated with default setting |
@@ -164,11 +191,22 @@ public class BrowserActionsIntent { |
"Exceeded maximum toolbar item count of " + MAX_CUSTOM_ITEMS); |
} |
for (int i = 0; i < items.size(); i++) { |
+ assert items.get(i).getTitle() != null; |
Yusuf
2017/07/14 05:35:34
assert would not help with production builds so th
ltian
2017/07/14 22:15:02
Done.
|
+ assert items.get(i).getAction() != null; |
mMenuItems.add(getBundleFromItem(items.get(i))); |
} |
return this; |
} |
+ /** |
+ * Set the PendingIntent to be launched when a a browser specified menu item is selected. |
+ * @param onItemSelectedPendingIntent The PendingIntent to be launched. |
+ */ |
+ public Builder setSelectedAction(PendingIntent onItemSelectedPendingIntent) { |
Yusuf
2017/07/14 05:35:35
setOnItemSelectedAction
ltian
2017/07/14 22:15:02
Done.
|
+ mOnItemSelectedPendingIntent = onItemSelectedPendingIntent; |
+ return this; |
+ } |
+ |
/** |
* Populates a {@link Bundle} to hold a custom item for Browser Actions menu. |
* @param item A custom item for Browser Actions menu. |
@@ -192,62 +230,97 @@ public class BrowserActionsIntent { |
mIntent.putParcelableArrayListExtra(EXTRA_MENU_ITEMS, mMenuItems); |
PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, new Intent(), 0); |
mIntent.putExtra(EXTRA_APP_ID, pendingIntent); |
+ mIntent.putExtra(EXTRA_SELECTED_ACTION_PENDING_INTENT, mOnItemSelectedPendingIntent); |
return new BrowserActionsIntent(mIntent); |
} |
} |
/** |
- * Open a Browser Actions menu with default settings. |
- * It first checks if any Browser Actions provider is available to create a context menu. |
- * If not, open a Browser Actions menu locally from support library. |
+ * Construct a BrowserActionsIntent with default settings and launch it to open a Browser Actions menu. |
* @param context The context requesting for a Browser Actions menu. |
* @param uri The url for Browser Actions menu. |
*/ |
public static void openBrowserAction(Context context, Uri uri) { |
- if (hasBrowserActionsIntentHandler(context)) { |
- BrowserActionsIntent intent = new BrowserActionsIntent.Builder(context, uri).build(); |
- ContextCompat.startActivity(context, intent.getIntent(), null); |
- } else { |
- openFallbackBrowserActionsMenu( |
- context, uri, URL_TYPE_NONE, new ArrayList<BrowserActionItem>()); |
- } |
+ BrowserActionsIntent intent = new BrowserActionsIntent.Builder(context, uri).build(); |
+ launchIntent(context, intent.getIntent()); |
} |
/** |
- * Open a Browser Actions menu with custom items. |
- * It first checks if any Browser Actions provider is available to create a context menu. |
- * If not, open a Browser Actions menu locally from support library. |
+ * Construct a BrowserActionsIntent with custom settings and launch it to open a Browser Actions menu. |
* @param context The context requesting for a Browser Actions menu. |
* @param uri The url for Browser Actions menu. |
* @param type The type of the url for context menu to be opened. |
* @param items List of custom items to be added to Browser Actions menu. |
+ * @param pendingIntent The PendingIntent to be launched when a browser specified menu item is |
+ * selected. The browser will perform the PendingIntent so this should only go to a {@link |
+ * BroadcastReceiver}. |
+ */ |
+ public static void openBrowserAction(Context context, Uri uri, int type, |
+ ArrayList<BrowserActionItem> items, PendingIntent pendingIntent) { |
+ BrowserActionsIntent intent = new BrowserActionsIntent.Builder(context, uri) |
+ .setUrlType(type) |
+ .setCustomItems(items) |
+ .setSelectedAction(pendingIntent) |
+ .build(); |
+ launchIntent(context, intent.getIntent()); |
+ } |
+ |
+ /** |
+ * Launch an Intent to open a Browser Actions menu. |
+ * It first checks if any Browser Actions provider is available to create the menu. |
+ * If the default Browser supports Browser Actions, menu will be opened by the default Browser, |
+ * otherwise show a intent picker. |
+ * If not provider, a Browser Actions menu is opened locally from support library. |
+ * @param context The context requesting for a Browser Actions menu. |
+ * @param intent The {@link Intent} holds the setting for Browser Actions menu. |
*/ |
- public static void openBrowserAction( |
- Context context, Uri uri, int type, ArrayList<BrowserActionItem> items) { |
- if (hasBrowserActionsIntentHandler(context)) { |
- BrowserActionsIntent intent = new BrowserActionsIntent.Builder(context, uri) |
- .setUrlType(type) |
- .setCustomItems(items) |
- .build(); |
- ContextCompat.startActivity(context, intent.getIntent(), null); |
+ public static void launchIntent(Context context, Intent intent) { |
+ List<ResolveInfo> handlers = getBrowserActionsIntentHandlers(context); |
+ if (handlers == null || handlers.size() == 0) { |
+ openFallbackBrowserActionsMenu(context, intent); |
+ return; |
+ } else if (handlers.size() == 1) { |
+ intent.setPackage(handlers.get(0).activityInfo.packageName); |
} else { |
- openFallbackBrowserActionsMenu(context, uri, type, items); |
+ Intent viewIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(TEST_URL)); |
+ ResolveInfo defaultHandler = CustomTabsClient.getDefaultHandlerForIntent(context.getPackageManager(), viewIntent); |
Yusuf
2017/07/14 05:35:34
indentation wrong here?
ltian
2017/07/14 22:15:02
After revert it back, there should be no problem.
|
+ if (defaultHandler != null) { |
+ String defaultPackageName = defaultHandler.activityInfo.packageName; |
+ for (int i = 0; i < handlers.size(); i++) { |
+ if (defaultPackageName.equals(handlers.get(i).activityInfo.packageName)) { |
+ intent.setPackage(defaultPackageName); |
+ break; |
+ } |
+ } |
+ } |
} |
+ ContextCompat.startActivity(context, intent, null); |
} |
/** |
- * Check whether any Browser Actions provider is available to handle the {@link |
+ * Returns a list of Browser Actions providers available to handle the {@link |
* BrowserActionsIntent}. |
* @param context The context requesting for a Browser Actions menu. |
- * @return true If a Browser Actions provider is available handle the intent. |
+ * @return List of Browser Actions providers available to handle the intent. |
*/ |
- private static boolean hasBrowserActionsIntentHandler(Context context) { |
+ private static List<ResolveInfo> getBrowserActionsIntentHandlers(Context context) { |
Intent intent = |
new Intent(BrowserActionsIntent.ACTION_BROWSER_ACTIONS_OPEN, Uri.parse(TEST_URL)); |
PackageManager pm = context.getPackageManager(); |
- List<ResolveInfo> resolveInfoList = |
- pm.queryIntentActivities(intent, PackageManager.MATCH_ALL); |
- return resolveInfoList.size() > 0 ? true : false; |
+ return pm.queryIntentActivities(intent, PackageManager.MATCH_ALL); |
+ } |
+ |
+ private static void openFallbackBrowserActionsMenu( |
+ Context context, BrowserActionsIntent browserActionsIntent) { |
+ openFallbackBrowserActionsMenu(context, browserActionsIntent.getIntent()); |
+ } |
+ |
+ private static void openFallbackBrowserActionsMenu(Context context, Intent intent) { |
+ Uri uri = intent.getData(); |
+ int type = intent.getIntExtra(EXTRA_TYPE, URL_TYPE_NONE); |
+ ArrayList<Bundle> bundles = intent.getParcelableArrayListExtra(EXTRA_MENU_ITEMS); |
+ List<BrowserActionItem> items = bundles != null ? parseBrowserActionItems(bundles) : null; |
+ openFallbackBrowserActionsMenu(context, uri, type, items); |
} |
/** |
@@ -258,10 +331,39 @@ public class BrowserActionsIntent { |
* @param items List of custom items to add to Browser Actions menu. |
*/ |
private static void openFallbackBrowserActionsMenu( |
- Context context, Uri uri, int type, ArrayList<BrowserActionItem> items) { |
+ Context context, Uri uri, int type, List<BrowserActionItem> items) { |
return; |
} |
+ /** |
+ * Gets custom item list for browser action menu. |
+ * @param bundles Data for custom items from {@link BrowserActionsIntent}. |
+ * @return List of {@link BrowserActionItem} |
+ */ |
+ public static List<BrowserActionItem> parseBrowserActionItems(ArrayList<Bundle> bundles) { |
+ List<BrowserActionItem> mActions = new ArrayList<>(); |
+ for (int i = 0; i < bundles.size(); i++) { |
+ Bundle bundle = bundles.get(i); |
+ String title = bundle.getString(BrowserActionsIntent.KEY_TITLE); |
+ PendingIntent action = bundle.getParcelable(BrowserActionsIntent.KEY_ACTION); |
+ Bitmap icon = bundle.getParcelable(BrowserActionsIntent.KEY_ICON); |
+ if (title != null && action != null) { |
+ BrowserActionItem item = new BrowserActionItem(title, action); |
+ if (icon != null) { |
+ item.setIcon(icon); |
+ } |
+ mActions.add(item); |
+ } else if (title != null) { |
+ Log.e(TAG, "Missing action for item: " + i); |
Yusuf
2017/07/14 05:35:34
These are still here?
ltian
2017/07/14 22:15:02
The reason I still leave these checks here is beca
Yusuf
2017/07/17 17:08:52
Then again, we should be throwing IllegalArgumentE
|
+ } else if (action != null) { |
+ Log.e(TAG, "Missing title for item: " + i); |
+ } else { |
+ Log.e(TAG, "Missing title and action for item: " + i); |
+ } |
+ } |
+ return mActions; |
+ } |
+ |
/** |
* Get the package name of the creator application. |
* @param intent The {@link BrowserActionsIntent}. |