Exposing some methods to make QSB customization easier
Bug: 110336301 Change-Id: I74d73bfd4b345bae2ecab144b37f1af1126e4725
This commit is contained in:
parent
260b4cbd90
commit
95cded5424
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue