Skip to content

Commit

Permalink
Merge pull request #2358 from marunjar/reconfigure_widgets
Browse files Browse the repository at this point in the history
allow reconfigure of widgets
  • Loading branch information
marunjar authored Jan 1, 2025
2 parents 7db7c2f + 8cf3015 commit 100a7b3
Show file tree
Hide file tree
Showing 5 changed files with 122 additions and 66 deletions.
57 changes: 34 additions & 23 deletions app/src/main/java/fr/neamar/kiss/PickAppWidgetActivity.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package fr.neamar.kiss;

import static android.appwidget.AppWidgetProviderInfo.WIDGET_FEATURE_HIDE_FROM_PICKER;

import android.app.Activity;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProviderInfo;
Expand Down Expand Up @@ -126,35 +128,44 @@ private static List<WidgetInfo> getWidgetList(@NonNull Context context) {
List<WidgetInfo> infoList = new ArrayList<>(installedProviders.size());
PackageManager packageManager = context.getPackageManager();
for (AppWidgetProviderInfo providerInfo : installedProviders) {
// get widget name
String label = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
label = providerInfo.loadLabel(packageManager);
}
if (label == null) {
label = providerInfo.label;
}
if (!isHiddenFromPicker(providerInfo)) {
// get widget name
String label = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
label = providerInfo.loadLabel(packageManager);
}
if (label == null) {
label = providerInfo.label;
}

// get widget description
String description = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
CharSequence desc = providerInfo.loadDescription(context);
if (desc != null)
description = desc.toString();
}
// get widget description
String description = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
CharSequence desc = providerInfo.loadDescription(context);
if (desc != null)
description = desc.toString();
}

String appName = providerInfo.provider.getPackageName();
try {
ApplicationInfo appInfo = packageManager.getApplicationInfo(providerInfo.provider.getPackageName(), 0);
appName = appInfo.loadLabel(packageManager).toString();
} catch (Exception e) {
Log.e(TAG, "get `" + providerInfo.provider.getPackageName() + "` label");
String appName = providerInfo.provider.getPackageName();
try {
ApplicationInfo appInfo = packageManager.getApplicationInfo(providerInfo.provider.getPackageName(), 0);
appName = appInfo.loadLabel(packageManager).toString();
} catch (Exception e) {
Log.e(TAG, "get `" + providerInfo.provider.getPackageName() + "` label");
}
infoList.add(new WidgetInfo(appName, label, description, providerInfo));
}
infoList.add(new WidgetInfo(appName, label, description, providerInfo));
}
return infoList;
}

private static boolean isHiddenFromPicker(AppWidgetProviderInfo providerInfo) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
return (providerInfo.widgetFeatures & WIDGET_FEATURE_HIDE_FROM_PICKER) != 0;
}
return false;
}

@WorkerThread
private static Drawable getWidgetPreview(@NonNull Context context, @NonNull AppWidgetProviderInfo info) {
Drawable preview = null;
Expand Down Expand Up @@ -219,7 +230,7 @@ private WidgetInfo(String app, String name, String description, AppWidgetProvide
}
}

private interface MenuItem {
public interface MenuItem {
@NonNull
String getName();
}
Expand Down
97 changes: 73 additions & 24 deletions app/src/main/java/fr/neamar/kiss/forwarder/Widgets.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package fr.neamar.kiss.forwarder;

import static android.appwidget.AppWidgetProviderInfo.WIDGET_FEATURE_CONFIGURATION_OPTIONAL;
import static android.appwidget.AppWidgetProviderInfo.WIDGET_FEATURE_RECONFIGURABLE;

import android.app.Activity;
import android.appwidget.AppWidgetHost;
import android.appwidget.AppWidgetHostView;
Expand Down Expand Up @@ -43,6 +46,7 @@ class Widgets extends Forwarder {
private static final int REQUEST_APPWIDGET_PICKED = 9;
private static final int REQUEST_APPWIDGET_BOUND = 11;
private static final int REQUEST_APPWIDGET_CONFIGURED = 5;
private static final int REQUEST_APPWIDGET_RECONFIGURED = 13;

private static final int APPWIDGET_HOST_ID = 442;

Expand Down Expand Up @@ -82,11 +86,12 @@ void onActivityResult(int requestCode, int resultCode, Intent data) {
case Activity.RESULT_OK:
switch (requestCode) {
case REQUEST_APPWIDGET_CONFIGURED:
case REQUEST_APPWIDGET_RECONFIGURED:
Log.i(TAG, "Widget configured");
break;
case REQUEST_APPWIDGET_BOUND:
if (data != null) {
configureAppWidget(data);
addAppWidget(data);
} else {
Log.i(TAG, "Widget bind failed");
}
Expand All @@ -100,7 +105,7 @@ void onActivityResult(int requestCode, int resultCode, Intent data) {
}
}
// if binding not required we can continue with adding the widget
configureAppWidget(data);
addAppWidget(data);
} else {
Log.i(TAG, "Widget picker failed");
}
Expand All @@ -113,8 +118,8 @@ void onActivityResult(int requestCode, int resultCode, Intent data) {
requestCode == REQUEST_APPWIDGET_PICKED)
&& data != null) {
// if widget was not selected, delete it
int appWidgetId = data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);
if (appWidgetId != -1) {
int appWidgetId = data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
if (appWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID) {
// find widget views for appWidgetId
List<View> viewsToRemove = new ArrayList<>();
for (int i = 0; i < widgetArea.getChildCount(); i++) {
Expand Down Expand Up @@ -250,9 +255,8 @@ private void addWidget(int appWidgetId, int lineSize) {
ListPopup popupMenu = new ListPopup(mainActivity);
popupMenu.setAdapter(popupMenuAdapter);
popupMenu.setOnItemClickListener((adapter1, view, position) -> {
popupMenu.dismiss();
@StringRes int stringId = ((ListPopup.Item) adapter1.getItem(position)).stringId;
popupMenuClickHandler(view.getContext(), stringId, widgetWithMenuCurrentlyDisplayed);
popupMenuClickHandler(stringId, widgetWithMenuCurrentlyDisplayed);
});
mainActivity.registerPopup(popupMenu);
popupMenu.show(hostView);
Expand All @@ -267,6 +271,9 @@ private void addWidget(int appWidgetId, int lineSize) {
private void buildPopupMenu(Context context, ArrayAdapter<ListPopup.Item> adapter, AppWidgetProviderInfo currentAppWidgetInfo, AppWidgetHostView widgetWithMenuCurrentlyDisplayed) {
final ViewGroup parent = (ViewGroup) widgetWithMenuCurrentlyDisplayed.getParent();

if (isReconfigurable(currentAppWidgetInfo)) {
adapter.add(new ListPopup.Item(context, R.string.menu_widget_settings));
}
int increasedLineHeight = getIncreasedLineHeight(widgetWithMenuCurrentlyDisplayed);
if (!preventIncreaseLineHeight(increasedLineHeight, currentAppWidgetInfo)) {
adapter.add(new ListPopup.Item(context, R.string.menu_size_up));
Expand All @@ -284,9 +291,11 @@ private void buildPopupMenu(Context context, ArrayAdapter<ListPopup.Item> adapte
adapter.add(new ListPopup.Item(context, R.string.menu_widget_remove));
}

private void popupMenuClickHandler(Context context, @StringRes int stringId, AppWidgetHostView widgetWithMenuCurrentlyDisplayed) {
private void popupMenuClickHandler(@StringRes int stringId, AppWidgetHostView widgetWithMenuCurrentlyDisplayed) {
final ViewGroup parent = (ViewGroup) widgetWithMenuCurrentlyDisplayed.getParent();
if (stringId == R.string.menu_widget_remove) {
if (stringId == R.string.menu_widget_settings) {
reConfigureAppWidget(widgetWithMenuCurrentlyDisplayed.getAppWidgetId());
} else if (stringId == R.string.menu_widget_remove) {
parent.removeView(widgetWithMenuCurrentlyDisplayed);
mAppWidgetHost.deleteAppWidgetId(widgetWithMenuCurrentlyDisplayed.getAppWidgetId());
serializeState();
Expand Down Expand Up @@ -337,7 +346,7 @@ private int getIncreasedLineHeight(AppWidgetHostView hostView) {
* @param hostView host view for widget
* @param height height of widget
*/
private void setWidgetSize(AppWidgetHostView hostView, int height, AppWidgetProviderInfo appWidgetInfo) {
private void setWidgetSize(AppWidgetHostView hostView, int height, @NonNull AppWidgetProviderInfo appWidgetInfo) {
hostView.setMinimumHeight(height);
hostView.setMinimumWidth(Math.min(appWidgetInfo.minWidth, appWidgetInfo.minResizeWidth));
ViewGroup.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, height);
Expand Down Expand Up @@ -388,12 +397,10 @@ private boolean preventIncreaseLineHeight(int height, AppWidgetProviderInfo appW
/**
* Adds widget to Activity and persists it in prefs to be able to restore it
*
* @param data Intent holding widget id to add
* @param appWidgetId id of widget to add
* @param appWidgetInfo
*/
private void addAppWidget(Intent data) {
int appWidgetId = data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);
AppWidgetProviderInfo appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(appWidgetId);

private void addAppWidget(int appWidgetId, AppWidgetProviderInfo appWidgetInfo) {
// calculate already used lines
int usedLines = 0;
for (int i = 0; i < widgetArea.getChildCount(); i++) {
Expand All @@ -413,7 +420,7 @@ private void addAppWidget(Intent data) {

@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
private static void requestBindWidget(@NonNull Activity activity, @NonNull Intent data) {
final int appWidgetId = data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, 0);
final int appWidgetId = data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
final ComponentName provider = data.getParcelableExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER);
final UserHandle profile;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
Expand Down Expand Up @@ -442,31 +449,73 @@ private static void requestBindWidget(@NonNull Activity activity, @NonNull Inten
*
* @param data Intent holding widget id to configure
*/
private void configureAppWidget(Intent data) {
int appWidgetId = data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);

private void addAppWidget(Intent data) {
int appWidgetId = data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
AppWidgetProviderInfo appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(appWidgetId);
if (appWidgetInfo != null) {
// Add the widget
addAppWidget(appWidgetId, appWidgetInfo);

if (!isConfigurationOptional(appWidgetInfo)) {
configureAppWidget(appWidgetId, appWidgetInfo, REQUEST_APPWIDGET_CONFIGURED);
}
}
}

// Add the widget
addAppWidget(data);
private void reConfigureAppWidget(int appWidgetId) {
AppWidgetProviderInfo appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(appWidgetId);
configureAppWidget(appWidgetId, appWidgetInfo, REQUEST_APPWIDGET_RECONFIGURED);
}

if (appWidgetInfo.configure != null) {
// Launch over to configure widget, if needed.
private void configureAppWidget(int appWidgetId, AppWidgetProviderInfo appWidgetInfo, int requestCode) {
if (appWidgetInfo != null && appWidgetInfo.configure != null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
mAppWidgetHost.startAppWidgetConfigureActivityForResult(mainActivity, appWidgetId, 0, REQUEST_APPWIDGET_CONFIGURED, null);
mAppWidgetHost.startAppWidgetConfigureActivityForResult(mainActivity, appWidgetId, 0, requestCode, null);
} else {
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE);
intent.setComponent(appWidgetInfo.configure);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
try {
mainActivity.startActivityForResult(intent, REQUEST_APPWIDGET_CONFIGURED);
mainActivity.startActivityForResult(intent, requestCode);
} catch (SecurityException e) {
Toast.makeText(mainActivity, "KISS doesn't have permission to setup this widget. Believe this is a bug? Please open an issue at https://github.com/Neamar/KISS/issues", Toast.LENGTH_LONG).show();
}
}
}
}

/**
* A widget's configuration is optional only if it's configuration is marked as optional AND
* it can be reconfigured later.
*
* @param appWidgetInfo
* @return true, if configuration is optional
*/
private boolean isConfigurationOptional(@NonNull AppWidgetProviderInfo appWidgetInfo) {
if (!isReconfigurable(appWidgetInfo)) {
return false;
}
if (appWidgetInfo.configure != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
int featureFlags = appWidgetInfo.widgetFeatures;
return (featureFlags & WIDGET_FEATURE_CONFIGURATION_OPTIONAL) != 0;
} else {
return false;
}
}

/**
* @param appWidgetInfo
* @return true, if widget can be reconfigured
*/
private boolean isReconfigurable(@NonNull AppWidgetProviderInfo appWidgetInfo) {
if (appWidgetInfo.configure != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
int featureFlags = appWidgetInfo.widgetFeatures;
return (featureFlags & WIDGET_FEATURE_RECONFIGURABLE) != 0;
} else {
return false;
}
}

/**
* @param view
* @return calculated line size of given view
Expand Down
32 changes: 13 additions & 19 deletions app/src/main/java/fr/neamar/kiss/ui/ListPopup.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,27 +34,21 @@ public ListPopup(Context context) {
setWidth(LinearLayout.LayoutParams.WRAP_CONTENT);
setHeight(LinearLayout.LayoutParams.WRAP_CONTENT);
mItemClickListener = null;
mClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
if (dismissOnClick)
dismiss();
if (mItemClickListener != null) {
LinearLayout layout = getLinearLayout();
int position = layout.indexOfChild(v);
mItemClickListener.onItemClick(mAdapter, v, position);
}
mClickListener = view -> {
if (dismissOnClick)
dismiss();
if (mItemClickListener != null) {
LinearLayout layout2 = getLinearLayout();
int position = layout2.indexOfChild(view);
mItemClickListener.onItemClick(mAdapter, view, position);
}
};
mLongClickListener = new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
if (mItemLongClickListener == null)
return false;
LinearLayout layout = getLinearLayout();
int position = layout.indexOfChild(v);
return mItemLongClickListener.onItemLongClick(mAdapter, v, position);
}
mLongClickListener = view -> {
if (mItemLongClickListener == null)
return false;
LinearLayout layout1 = getLinearLayout();
int position = layout1.indexOfChild(view);
return mItemLongClickListener.onItemLongClick(mAdapter, view, position);
};
}

Expand Down
1 change: 1 addition & 0 deletions app/src/main/res/values-de/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@
<string name="large_search_bar">Größere Suchleiste</string>
<string name="menu_widget_add">Widget hinzufügen</string>
<string name="menu_widget_remove">Widget entfernen</string>
<string name="menu_widget_settings">Einstellungen</string>
<string name="lwp_touch">Touch-Eingaben an Hintergrund weiterleiten</string>
<string name="lwp_drag">Bewegungen emulieren</string>
<string name="lwp_drag_desc">Mehrere Touch-Ereignisse hintereinander senden</string>
Expand Down
1 change: 1 addition & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,7 @@
<string name="menu_size_up">Enlarge</string>
<string name="menu_widget_move_up">Move up</string>
<string name="menu_widget_move_down">Move down</string>
<string name="menu_widget_settings">Settings</string>
<string name="lock_service_description">Lock screen from KISS Launcher</string>
<string name="gesture_up_name">Action on swipe up</string>
<string name="gesture_down_name">Action on swipe down</string>
Expand Down

0 comments on commit 100a7b3

Please sign in to comment.