Exposing some methods to make QSB customization easier

Bug: 110336301
Change-Id: I74d73bfd4b345bae2ecab144b37f1af1126e4725
This commit is contained in:
Sunny Goyal 2018-06-14 20:08:57 -07:00
parent 260b4cbd90
commit 95cded5424
2 changed files with 90 additions and 79 deletions

View File

@ -16,6 +16,10 @@
package com.android.launcher3.qsb; package com.android.launcher3.qsb;
import static android.appwidget.AppWidgetManager.ACTION_APPWIDGET_BIND;
import static android.appwidget.AppWidgetManager.EXTRA_APPWIDGET_ID;
import static android.appwidget.AppWidgetManager.EXTRA_APPWIDGET_PROVIDER;
import android.app.Activity; import android.app.Activity;
import android.app.Fragment; import android.app.Fragment;
import android.app.SearchManager; import android.app.SearchManager;
@ -74,11 +78,12 @@ public class QsbContainerView extends FrameLayout {
/** /**
* A fragment to display the QSB. * A fragment to display the QSB.
*/ */
public static class QsbFragment extends Fragment implements View.OnClickListener { public static class QsbFragment extends Fragment {
public static final int QSB_WIDGET_HOST_ID = 1026;
private static final int REQUEST_BIND_QSB = 1; private static final int REQUEST_BIND_QSB = 1;
private static final String QSB_WIDGET_ID = "qsb_widget_id";
protected String mKeyWidgetId = "qsb_widget_id";
private QsbWidgetHost mQsbWidgetHost; private QsbWidgetHost mQsbWidgetHost;
private AppWidgetProviderInfo mWidgetInfo; private AppWidgetProviderInfo mWidgetInfo;
private QsbWidgetHostView mQsb; private QsbWidgetHostView mQsb;
@ -90,10 +95,15 @@ public class QsbContainerView extends FrameLayout {
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
mQsbWidgetHost = new QsbWidgetHost(getActivity()); mQsbWidgetHost = createHost();
mOrientation = getContext().getResources().getConfiguration().orientation; mOrientation = getContext().getResources().getConfiguration().orientation;
} }
protected QsbWidgetHost createHost() {
return new QsbWidgetHost(getActivity(), QSB_WIDGET_HOST_ID,
(c) -> new QsbWidgetHostView(c));
}
private FrameLayout mWrapper; private FrameLayout mWrapper;
@Override @Override
@ -110,24 +120,16 @@ public class QsbContainerView extends FrameLayout {
} }
private View createQsb(ViewGroup container) { private View createQsb(ViewGroup container) {
Activity activity = getActivity(); mWidgetInfo = getSearchWidgetProvider();
mWidgetInfo = getSearchWidgetProvider(activity);
if (mWidgetInfo == null) { if (mWidgetInfo == null) {
// There is no search provider, just show the default widget. // There is no search provider, just show the default widget.
return QsbWidgetHostView.getDefaultView(container); return getDefaultView(container, false /* show setup icon */);
} }
Bundle opts = createBindOptions();
Activity activity = getActivity();
AppWidgetManager widgetManager = AppWidgetManager.getInstance(activity); AppWidgetManager widgetManager = AppWidgetManager.getInstance(activity);
InvariantDeviceProfile idp = LauncherAppState.getIDP(activity);
Bundle opts = new Bundle(); int widgetId = Utilities.getPrefs(activity).getInt(mKeyWidgetId, -1);
Rect size = AppWidgetResizeFrame.getWidgetSizeRanges(activity, idp.numColumns, 1, null);
opts.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH, size.left);
opts.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT, size.top);
opts.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH, size.right);
opts.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT, size.bottom);
int widgetId = Utilities.getPrefs(activity).getInt(QSB_WIDGET_ID, -1);
AppWidgetProviderInfo widgetInfo = widgetManager.getAppWidgetInfo(widgetId); AppWidgetProviderInfo widgetInfo = widgetManager.getAppWidgetInfo(widgetId);
boolean isWidgetBound = (widgetInfo != null) && boolean isWidgetBound = (widgetInfo != null) &&
widgetInfo.provider.equals(mWidgetInfo.provider); widgetInfo.provider.equals(mWidgetInfo.provider);
@ -166,32 +168,18 @@ public class QsbContainerView extends FrameLayout {
} }
// Return a default widget with setup icon. // Return a default widget with setup icon.
View v = QsbWidgetHostView.getDefaultView(container); return getDefaultView(container, true /* show setup icon */);
View setupButton = v.findViewById(R.id.btn_qsb_setup);
setupButton.setVisibility(View.VISIBLE);
setupButton.setOnClickListener(this);
return v;
} }
private void saveWidgetId(int widgetId) { private void saveWidgetId(int widgetId) {
Utilities.getPrefs(getActivity()).edit().putInt(QSB_WIDGET_ID, widgetId).apply(); Utilities.getPrefs(getActivity()).edit().putInt(mKeyWidgetId, widgetId).apply();
}
@Override
public void onClick(View view) {
// Start intent for bind the widget
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_BIND);
// Allocate a new widget id for QSB
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mQsbWidgetHost.allocateAppWidgetId());
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER, mWidgetInfo.provider);
startActivityForResult(intent, REQUEST_BIND_QSB);
} }
@Override @Override
public void onActivityResult(int requestCode, int resultCode, Intent data) { public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_BIND_QSB) { if (requestCode == REQUEST_BIND_QSB) {
if (resultCode == Activity.RESULT_OK) { if (resultCode == Activity.RESULT_OK) {
saveWidgetId(data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1)); saveWidgetId(data.getIntExtra(EXTRA_APPWIDGET_ID, -1));
rebindFragment(); rebindFragment();
} else { } else {
mQsbWidgetHost.deleteHost(); mQsbWidgetHost.deleteHost();
@ -228,48 +216,83 @@ public class QsbContainerView extends FrameLayout {
public boolean isQsbEnabled() { public boolean isQsbEnabled() {
return FeatureFlags.QSB_ON_FIRST_SCREEN; return FeatureFlags.QSB_ON_FIRST_SCREEN;
} }
}
/** protected Bundle createBindOptions() {
* Returns a widget with category {@link AppWidgetProviderInfo#WIDGET_CATEGORY_SEARCHBOX} InvariantDeviceProfile idp = LauncherAppState.getIDP(getActivity());
* provided by the same package which is set to be global search activity.
* If widgetCategory is not supported, or no such widget is found, returns the first widget
* provided by the package.
*/
public static AppWidgetProviderInfo getSearchWidgetProvider(Context context) {
SearchManager searchManager =
(SearchManager) context.getSystemService(Context.SEARCH_SERVICE);
ComponentName searchComponent = searchManager.getGlobalSearchActivity();
if (searchComponent == null) return null;
String providerPkg = searchComponent.getPackageName();
AppWidgetProviderInfo defaultWidgetForSearchPackage = null; Bundle opts = new Bundle();
Rect size = AppWidgetResizeFrame.getWidgetSizeRanges(getActivity(),
idp.numColumns, 1, null);
opts.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH, size.left);
opts.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT, size.top);
opts.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH, size.right);
opts.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT, size.bottom);
return opts;
}
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context); protected View getDefaultView(ViewGroup container, boolean showSetupIcon) {
for (AppWidgetProviderInfo info : appWidgetManager.getInstalledProviders()) { // Return a default widget with setup icon.
if (info.provider.getPackageName().equals(providerPkg) && info.configure == null) { View v = QsbWidgetHostView.getDefaultView(container);
if ((info.widgetCategory & AppWidgetProviderInfo.WIDGET_CATEGORY_SEARCHBOX) != 0) { if (showSetupIcon) {
return info; View setupButton = v.findViewById(R.id.btn_qsb_setup);
} else if (defaultWidgetForSearchPackage == null) { setupButton.setVisibility(View.VISIBLE);
defaultWidgetForSearchPackage = info; setupButton.setOnClickListener((v2) -> startActivityForResult(
new Intent(ACTION_APPWIDGET_BIND)
.putExtra(EXTRA_APPWIDGET_ID, mQsbWidgetHost.allocateAppWidgetId())
.putExtra(EXTRA_APPWIDGET_PROVIDER, mWidgetInfo.provider),
REQUEST_BIND_QSB));
}
return v;
}
/**
* Returns a widget with category {@link AppWidgetProviderInfo#WIDGET_CATEGORY_SEARCHBOX}
* provided by the same package which is set to be global search activity.
* If widgetCategory is not supported, or no such widget is found, returns the first widget
* provided by the package.
*/
protected AppWidgetProviderInfo getSearchWidgetProvider() {
SearchManager searchManager =
(SearchManager) getActivity().getSystemService(Context.SEARCH_SERVICE);
ComponentName searchComponent = searchManager.getGlobalSearchActivity();
if (searchComponent == null) return null;
String providerPkg = searchComponent.getPackageName();
AppWidgetProviderInfo defaultWidgetForSearchPackage = null;
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(getActivity());
for (AppWidgetProviderInfo info : appWidgetManager.getInstalledProviders()) {
if (info.provider.getPackageName().equals(providerPkg) && info.configure == null) {
if ((info.widgetCategory
& AppWidgetProviderInfo.WIDGET_CATEGORY_SEARCHBOX) != 0) {
return info;
} else if (defaultWidgetForSearchPackage == null) {
defaultWidgetForSearchPackage = info;
}
} }
} }
return defaultWidgetForSearchPackage;
} }
return defaultWidgetForSearchPackage;
} }
private static class QsbWidgetHost extends AppWidgetHost { public static class QsbWidgetHost extends AppWidgetHost {
private static final int QSB_WIDGET_HOST_ID = 1026; private final WidgetViewFactory mViewFactory;
public QsbWidgetHost(Context context) { public QsbWidgetHost(Context context, int hostId, WidgetViewFactory viewFactory) {
super(context, QSB_WIDGET_HOST_ID); super(context, hostId);
mViewFactory = viewFactory;
} }
@Override @Override
protected AppWidgetHostView onCreateView( protected AppWidgetHostView onCreateView(
Context context, int appWidgetId, AppWidgetProviderInfo appWidget) { Context context, int appWidgetId, AppWidgetProviderInfo appWidget) {
return new QsbWidgetHostView(context); return mViewFactory.newView(context);
} }
} }
public interface WidgetViewFactory {
QsbWidgetHostView newView(Context context);
}
} }

View File

@ -58,13 +58,9 @@ public class QsbWidgetHostView extends AppWidgetHostView {
try { try {
super.onLayout(changed, left, top, right, bottom); super.onLayout(changed, left, top, right, bottom);
} catch (final RuntimeException e) { } catch (final RuntimeException e) {
post(new Runnable() { // Update the widget with 0 Layout id, to reset the view to error view.
@Override post(() -> updateAppWidget(
public void run() { new RemoteViews(getAppWidgetInfo().provider.getPackageName(), 0)));
// Update the widget with 0 Layout id, to reset the view to error view.
updateAppWidget(new RemoteViews(getAppWidgetInfo().provider.getPackageName(), 0));
}
});
} }
} }
@ -76,24 +72,16 @@ public class QsbWidgetHostView extends AppWidgetHostView {
@Override @Override
protected View getDefaultView() { protected View getDefaultView() {
View v = super.getDefaultView(); View v = super.getDefaultView();
v.setOnClickListener(new OnClickListener() { v.setOnClickListener((v2) ->
@Override Launcher.getLauncher(getContext()).startSearch("", false, null, true));
public void onClick(View view) {
Launcher.getLauncher(getContext()).startSearch("", false, null, true);
}
});
return v; return v;
} }
public static View getDefaultView(ViewGroup parent) { public static View getDefaultView(ViewGroup parent) {
View v = LayoutInflater.from(parent.getContext()) View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.qsb_default_view, parent, false); .inflate(R.layout.qsb_default_view, parent, false);
v.findViewById(R.id.btn_qsb_search).setOnClickListener(new OnClickListener() { v.findViewById(R.id.btn_qsb_search).setOnClickListener((v2) ->
@Override Launcher.getLauncher(v2.getContext()).startSearch("", false, null, true));
public void onClick(View view) {
Launcher.getLauncher(view.getContext()).startSearch("", false, null, true);
}
});
return v; return v;
} }
} }