Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e5900691 authored by Amit Kumar's avatar Amit Kumar
Browse files

Add custom widget picker instead of default

parent 060c7655
Loading
Loading
Loading
Loading
+9 −4
Original line number Original line Diff line number Diff line
@@ -115,10 +115,15 @@
        <activity android:name=".features.widgets.WidgetsActivity"
        <activity android:name=".features.widgets.WidgetsActivity"
                  android:autoRemoveFromRecents="true"
                  android:autoRemoveFromRecents="true"
                  android:excludeFromRecents="true"
                  android:excludeFromRecents="true"
                  android:theme="@android:style/Theme.Material.Light.DarkActionBar"
                  android:theme="@style/AppTheme"
                  android:label="Widgets">
                  android:label="Widgets"/>

        <activity android:name=".features.widgets.WidgetPicker"
        </activity>
                  android:autoRemoveFromRecents="true"
                  android:excludeFromRecents="true"
                  android:theme="@style/WidgetPickerDialog"
                  android:finishOnCloseSystemDialogs="true"
                  android:label="Choose widget"
        android:exported="true"/>
    </application>
    </application>


</manifest>
</manifest>
 No newline at end of file
+3 −3
Original line number Original line Diff line number Diff line
@@ -34,7 +34,8 @@ public class AddedWidgetsAdapter extends
    @NonNull
    @NonNull
    @Override
    @Override
    public WidgetsViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
    public WidgetsViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
        View view = LayoutInflater.from(mContext).inflate(R.layout.item_widget_all, viewGroup, false);
        View view = LayoutInflater.from(mContext).inflate(R.layout.item_added_widget, viewGroup,
                false);
        WidgetsViewHolder widgetsViewHolder = new WidgetsViewHolder(view);
        WidgetsViewHolder widgetsViewHolder = new WidgetsViewHolder(view);
        widgetsViewHolder.actionBtn.setImageResource(R.drawable.ic_remove_widget_red_24dp);
        widgetsViewHolder.actionBtn.setImageResource(R.drawable.ic_remove_widget_red_24dp);
        widgetsViewHolder.actionBtn.setOnClickListener(
        widgetsViewHolder.actionBtn.setOnClickListener(
@@ -79,7 +80,6 @@ public class AddedWidgetsAdapter extends
            label = itemView.findViewById(R.id.widget_label);
            label = itemView.findViewById(R.id.widget_label);
            actionBtn = itemView.findViewById(R.id.action_image_view);
            actionBtn = itemView.findViewById(R.id.action_image_view);
        }
        }

    }
    }


    interface OnActionClickListener {
    interface OnActionClickListener {
+218 −0
Original line number Original line Diff line number Diff line
package foundation.e.blisslauncher.features.widgets;

import android.app.Activity;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProviderInfo;
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Parcelable;
import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.DisplayMetrics;
import android.util.Log;
import android.widget.Toast;

import java.text.Collator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import foundation.e.blisslauncher.R;

public class WidgetPicker extends Activity implements WidgetPickerAdapter.OnClickListener {

    private static final int REQUEST_BIND_APPWIDGET = 111;
    private int mAppWidgetId;

    private AppWidgetManager mAppWidgetManager;
    private PackageManager mPackageManager;

    private static final String TAG = "WidgetPicker";
    private Intent mBaseIntent;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        mPackageManager = getPackageManager();
        mAppWidgetManager = AppWidgetManager.getInstance(this);

        super.onCreate(savedInstanceState);

        // Set default return data
        setResultData(RESULT_CANCELED, null);

        // Read the appWidgetId passed our direction, otherwise bail if not found
        final Intent intent = getIntent();
        if (intent.hasExtra(AppWidgetManager.EXTRA_APPWIDGET_ID)) {
            mAppWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
                    AppWidgetManager.INVALID_APPWIDGET_ID);
        } else {
            finish();
        }

        // Read base intent from extras, otherwise assume default
        Parcelable parcel = intent.getParcelableExtra(Intent.EXTRA_INTENT);
        if (parcel instanceof Intent) {
            mBaseIntent = (Intent) parcel;
            mBaseIntent.setFlags(mBaseIntent.getFlags() & ~(Intent.FLAG_GRANT_READ_URI_PERMISSION
                    | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
                    | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
                    | Intent.FLAG_GRANT_PREFIX_URI_PERMISSION));
        } else {
            mBaseIntent = new Intent(Intent.ACTION_MAIN, null);
            mBaseIntent.addCategory(Intent.CATEGORY_DEFAULT);
        }

        setContentView(R.layout.activity_widget_picker);
        RecyclerView recyclerView = findViewById(R.id.all_widgets_recycler_view);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        recyclerView.setHasFixedSize(true);
        recyclerView.addItemDecoration(
                new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));
        WidgetPickerAdapter adapter = new WidgetPickerAdapter(this);
        recyclerView.setAdapter(adapter);
        List<WidgetPickerAdapter.Item> items = new ArrayList<>();
        putInstalledAppWidgets(items);
        Collections.sort(items, new Comparator<WidgetPickerAdapter.Item>() {
            Collator mCollator = Collator.getInstance();

            public int compare(WidgetPickerAdapter.Item lhs, WidgetPickerAdapter.Item rhs) {
                return mCollator.compare(lhs.getLabel(), rhs.getLabel());
            }
        });
        adapter.setItems(items);
    }

    private void putInstalledAppWidgets(List<WidgetPickerAdapter.Item> items) {
        List<AppWidgetProviderInfo> installed =
                mAppWidgetManager.getInstalledProviders();
        if (installed == null) return;
        final int size = installed.size();
        for (int i = 0; i < size; i++) {
            AppWidgetProviderInfo info = installed.get(i);
            items.add(createItem(info));
        }
    }

    public WidgetPickerAdapter.Item createItem(AppWidgetProviderInfo info) {
        CharSequence label = info.loadLabel(mPackageManager);
        Drawable icon = null;
        if (info.icon != 0) {
            try {
                final Resources res = getResources();
                final int density = res.getDisplayMetrics().densityDpi;
                int iconDensity;
                switch (density) {
                    case DisplayMetrics.DENSITY_MEDIUM:
                        iconDensity = DisplayMetrics.DENSITY_LOW;
                        break;
                    case DisplayMetrics.DENSITY_TV:
                        iconDensity = DisplayMetrics.DENSITY_MEDIUM;
                        break;
                    case DisplayMetrics.DENSITY_HIGH:
                        iconDensity = DisplayMetrics.DENSITY_MEDIUM;
                        break;
                    case DisplayMetrics.DENSITY_XHIGH:
                        iconDensity = DisplayMetrics.DENSITY_HIGH;
                        break;
                    case DisplayMetrics.DENSITY_XXHIGH:
                        iconDensity = DisplayMetrics.DENSITY_XHIGH;
                        break;
                    default:
                        // The density is some abnormal value.  Return some other
                        // abnormal value that is a reasonable scaling of it.
                        iconDensity = (int) ((density * 0.75f) + .5f);
                }
                Resources packageResources = mPackageManager.
                        getResourcesForApplication(info.provider.getPackageName());
                icon = packageResources.getDrawableForDensity(info.icon, iconDensity);
            } catch (PackageManager.NameNotFoundException e) {
                Log.w(TAG, "Can't load icon drawable 0x" + Integer.toHexString(info.icon)
                        + " for provider: " + info.provider);
            }
            if (icon == null) {
                Log.w(TAG, "Can't load icon drawable 0x" + Integer.toHexString(info.icon)
                        + " for provider: " + info.provider);
            }
        }
        WidgetPickerAdapter.Item item = new WidgetPickerAdapter.Item(label, icon);
        item.packageName = info.provider.getPackageName();
        item.className = info.provider.getClassName();
        item.profile = info.getProfile();
        return item;
    }

    @Override
    public void onClick(WidgetPickerAdapter.Item item) {
        Intent intent = item.getIntent(mBaseIntent);
        int result = -10;
        if (item.extras != null) {
            setResultData(RESULT_OK, intent);
        } else {
            try {
                Bundle options = null;
                if (intent.getExtras() != null) {
                    options = intent.getExtras().getBundle(
                            AppWidgetManager.EXTRA_APPWIDGET_OPTIONS);
                }

                boolean success = mAppWidgetManager.bindAppWidgetIdIfAllowed(mAppWidgetId,
                        intent.getComponent(), options);
                if (success) {
                    result = RESULT_OK;
                } else {
                    Intent permissionIntent = new Intent(AppWidgetManager.ACTION_APPWIDGET_BIND);
                    permissionIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
                    permissionIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER,
                            new ComponentName(item.packageName, item.className));
                    intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER_PROFILE,
                            item.profile);
                    // TODO: we need to make sure that this accounts for the options bundle.
                    // intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS, options);
                    startActivityForResult(permissionIntent, REQUEST_BIND_APPWIDGET);
                }

            } catch (IllegalArgumentException e) {
                result = RESULT_CANCELED;
            }
            setResultData(result, null);
        }
        finish();
    }

    /**
     * Convenience method for setting the result code and intent. This method
     * correctly injects the {@link AppWidgetManager#EXTRA_APPWIDGET_ID} that
     * most hosts expect returned.
     */
    void setResultData(int code, Intent intent) {
        Intent result = intent != null ? intent : new Intent();
        result.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
        setResult(code, result);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        Log.d(TAG, "onActivityResult() called with: requestCode = [" + requestCode
                + "], resultCode = [" + resultCode + "], data = [" + data + "]");
        if (requestCode == REQUEST_BIND_APPWIDGET) {
            int appWidgetId = data != null ?
                    data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1) : -1;
            if (resultCode == RESULT_OK) {
                setResultData(RESULT_OK, null);
            } else {
                Toast.makeText(this, "Permission denied", Toast.LENGTH_SHORT).show();
                setResultData(RESULT_CANCELED, null);
            }

            finish();
        } else {
            super.onActivityResult(requestCode, resultCode, data);
        }
    }
}
+142 −0
Original line number Original line Diff line number Diff line
package foundation.e.blisslauncher.features.widgets;

import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.UserHandle;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;

import foundation.e.blisslauncher.R;

public class WidgetPickerAdapter extends
        RecyclerView.Adapter<WidgetPickerAdapter.WidgetsViewHolder> {

    private Context mContext;
    private List<Item> mItems = new ArrayList<>();

    private OnClickListener mOnClickListener;
    private static final String TAG = "AddedWidgetsAdapter";

    public WidgetPickerAdapter(Context context) {
        this.mContext = context;
        mOnClickListener = (OnClickListener) mContext;
    }

    @NonNull
    @Override
    public WidgetsViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
        View view = LayoutInflater.from(mContext).inflate(R.layout.item_all_widget, viewGroup,
                false);
        WidgetsViewHolder widgetsViewHolder = new WidgetsViewHolder(view);
        widgetsViewHolder.itemView.setOnClickListener(v -> {
            int position = widgetsViewHolder.getAdapterPosition();
            if (position != RecyclerView.NO_POSITION){
                mOnClickListener.onClick(mItems.get(position));
            }
        });
        return widgetsViewHolder;
    }

    @Override
    public void onBindViewHolder(@NonNull WidgetsViewHolder widgetsViewHolder, int i) {
        Item info = mItems.get(i);
        widgetsViewHolder.icon.setImageDrawable(info.icon);
        widgetsViewHolder.label.setText(info.label);
    }

    @Override
    public int getItemCount() {
        return mItems.size();
    }

    public void setItems(List<Item> items) {
        this.mItems = items;
        notifyDataSetChanged();
    }

    public static class WidgetsViewHolder extends RecyclerView.ViewHolder {

        ImageView icon;
        TextView label;

        public WidgetsViewHolder(@NonNull View itemView) {
            super(itemView);
            icon = itemView.findViewById(R.id.widget_icon);
            label = itemView.findViewById(R.id.widget_label);
        }

    }

    public static class Item {
        public UserHandle profile;
        CharSequence label;
        Drawable icon;
        String packageName;
        String className;
        Bundle extras;

        /**
         * Create a list item from given label and icon.
         */
        Item(CharSequence label, Drawable icon) {
            this.label = label;
            this.icon = icon;
        }

        /**
         * Create a list item and fill it with details from the given
         * {@link ResolveInfo} object.
         */
        Item(PackageManager pm, ResolveInfo resolveInfo) {
            label = resolveInfo.loadLabel(pm);
            if (label == null && resolveInfo.activityInfo != null) {
                label = resolveInfo.activityInfo.name;
            }

            icon = resolveInfo.loadIcon(pm);
            packageName = resolveInfo.activityInfo.applicationInfo.packageName;
            className = resolveInfo.activityInfo.name;
        }

        /**
         * Build the {@link Intent} described by this item. If this item
         * can't create a valid {@link android.content.ComponentName}, it will return
         * {@link Intent#ACTION_CREATE_SHORTCUT} filled with the item label.
         */
        Intent getIntent(Intent baseIntent) {
            Intent intent = new Intent(baseIntent);
            if (packageName != null && className != null) {
                // Valid package and class, so fill details as normal intent
                intent.setClassName(packageName, className);
                if (extras != null) {
                    intent.putExtras(extras);
                }
            } else {
                // No valid package or class, so treat as shortcut with label
                intent.setAction(Intent.ACTION_CREATE_SHORTCUT);
                intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, label);
            }
            return intent;
        }

        public CharSequence getLabel() {
            return label;
        }
    }

    interface OnClickListener {
        void onClick(Item item);
    }
}
+15 −3
Original line number Original line Diff line number Diff line
@@ -3,12 +3,14 @@ package foundation.e.blisslauncher.features.widgets;
import android.app.Activity;
import android.app.Activity;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProviderInfo;
import android.appwidget.AppWidgetProviderInfo;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.content.Intent;
import android.os.Bundle;
import android.os.Bundle;
import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.RecyclerView;
import android.util.DisplayMetrics;
import android.util.DisplayMetrics;
import android.widget.Toast;


import java.util.ArrayList;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Arrays;
@@ -81,7 +83,7 @@ public class WidgetsActivity extends Activity implements AddedWidgetsAdapter.OnA


    void selectWidget() {
    void selectWidget() {
        int appWidgetId = this.mAppWidgetHost.allocateAppWidgetId();
        int appWidgetId = this.mAppWidgetHost.allocateAppWidgetId();
        Intent pickIntent = new Intent(AppWidgetManager.ACTION_APPWIDGET_PICK);
        Intent pickIntent = new Intent(this, WidgetPicker.class);
        pickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
        pickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
        addEmptyData(pickIntent);
        addEmptyData(pickIntent);
        startActivityForResult(pickIntent, REQUEST_PICK_APPWIDGET);
        startActivityForResult(pickIntent, REQUEST_PICK_APPWIDGET);
@@ -117,10 +119,11 @@ public class WidgetsActivity extends Activity implements AddedWidgetsAdapter.OnA
        int appWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);
        int appWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);
        AppWidgetProviderInfo appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(appWidgetId);
        AppWidgetProviderInfo appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(appWidgetId);
        if (appWidgetInfo != null && appWidgetInfo.configure != null) {
        if (appWidgetInfo != null && appWidgetInfo.configure != null) {
            Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE);
            /*Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE);
            intent.setComponent(appWidgetInfo.configure);
            intent.setComponent(appWidgetInfo.configure);
            intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
            intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
            startActivityForResult(intent, REQUEST_CREATE_APPWIDGET);
            startActivityForResult(intent, REQUEST_CREATE_APPWIDGET);*/
            startAppWidgetConfigureActivitySafely(appWidgetId);
        } else {
        } else {
            createWidget(data);
            createWidget(data);
        }
        }
@@ -138,4 +141,13 @@ public class WidgetsActivity extends Activity implements AddedWidgetsAdapter.OnA
        refreshRecyclerView();
        refreshRecyclerView();
    }
    }


    void startAppWidgetConfigureActivitySafely(int appWidgetId) {
        try {
            mAppWidgetHost.startAppWidgetConfigureActivityForResult(this, appWidgetId, 0,
                    REQUEST_CREATE_APPWIDGET, null);
        } catch (ActivityNotFoundException e) {
            Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
        }
    }

}
}
Loading