How can you create a widget inside an android appl

2019-04-17 00:31发布

问题:

I need to create an application that contains multiple widgets. These are not desktop widgets. I need to be able to interact with these widgets as if they were desktop widgets, but they need to be encased inside a larger application. (Each widget has it's own functionality and behavior when clicked.)

Is this possible in android? Or do I need to create an application and create each object that I'd like to behave like a widget actually as a view?

Ex. The parent app is for a car. Example of "in app" widgets are: oil change history (list of last three oil change dates visible, clicking on a date will open a scan of the receipt, etc.), tire pressure monitor, lap speed history (shows last four laps, pinching and expanding will show more than four), etc.

Can I make each of these objects widgets? Or do they have to be views inside the app?

Edit: The Android developer's App Widget Host page mentions: "The AppWidgetHost provides the interaction with the AppWidget service for apps, like the home screen, that want to embed app widgets in their UI."
Has anyone created their own App Widget Host or worked directly with this class?

回答1:

Create your appwidget normally

Then in your activity add this code Call selectWidget() to open popup to pick avaible widget

//init
mAppWidgetManager = AppWidgetManager.getInstance(this);
mAppWidgetHost = new AppWidgetHost(this, R.id.APPWIDGET_HOST_ID);

//select widget
void selectWidget() {
    int appWidgetId = this.mAppWidgetHost.allocateAppWidgetId();
    Intent pickIntent = new Intent(AppWidgetManager.ACTION_APPWIDGET_PICK);
    pickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
    addEmptyData(pickIntent);
    startActivityForResult(pickIntent, R.id.REQUEST_PICK_APPWIDGET);
}
void addEmptyData(Intent pickIntent) {
    ArrayList customInfo = new ArrayList();
    pickIntent.putParcelableArrayListExtra(AppWidgetManager.EXTRA_CUSTOM_INFO, customInfo);
    ArrayList customExtras = new ArrayList();
    pickIntent.putParcelableArrayListExtra(AppWidgetManager.EXTRA_CUSTOM_EXTRAS, customExtras);
};

//Configure the widget
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (resultCode == RESULT_OK ) {
        if (requestCode == REQUEST_PICK_APPWIDGET) {
            configureWidget(data);
        }
        else if (requestCode == REQUEST_CREATE_APPWIDGET) {
            createWidget(data);
        }
    }
    else if (resultCode == RESULT_CANCELED && data != null) {
        int appWidgetId = data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);
        if (appWidgetId != -1) {
            mAppWidgetHost.deleteAppWidgetId(appWidgetId);
        }
    }
}

private void configureWidget(Intent data) {
    Bundle extras = data.getExtras();
    int appWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);
    AppWidgetProviderInfo appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(appWidgetId);
    if (appWidgetInfo.configure != null) {
        Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE);
        intent.setComponent(appWidgetInfo.configure);
        intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
        startActivityForResult(intent, REQUEST_CREATE_APPWIDGET);
    } else {
        createWidget(data);
    }
}

//adding it to you view
public void createWidget(Intent data) {
    Bundle extras = data.getExtras();
    int appWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);
    AppWidgetProviderInfo appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(appWidgetId);
    AppWidgetHostView hostView = mAppWidgetHost.createView(this, appWidgetId, appWidgetInfo);
    hostView.setAppWidget(appWidgetId, appWidgetInfo);
    layout.addView(hostView);
}

//Update widget
@Override
protected void onStart() {
    super.onStart();
    mAppWidgetHost.startListening();
}
@Override
protected void onStop() {
    super.onStop();
    mAppWidgetHost.stopListening();
}

//Now to remove it call this
public void removeWidget(AppWidgetHostView hostView) {
    mAppWidgetHost.deleteAppWidgetId(hostView.getAppWidgetId());
    layout.removeView(hostView);
}

Hope this helps



回答2:

If you want to embed a specific widget in your app, and know the package name and class name:

public boolean createWidget(View view, String packageName, String className) {
    // Get the list of installed widgets
    AppWidgetProviderInfo newAppWidgetProviderInfo = null;
    List<AppWidgetProviderInfo> appWidgetInfos;
    appWidgetInfos = mAppWidgetManager.getInstalledProviders();
    boolean widgetIsFound = false;
    for(int j = 0; j < appWidgetInfos.size(); j++)
    {
        if (appWidgetInfos.get(j).provider.getPackageName().equals(packageName) && appWidgetInfos.get(j).provider.getClassName().equals(className))
        {
            // Get the full info of the required widget
            newAppWidgetProviderInfo = appWidgetInfos.get(j);
            widgetIsFound = true;
            break;
        }
    }

    if (!widgetIsFound) {
        return false;
    } else {
        // Create Widget
        int appWidgetId = mAppWidgetHost.allocateAppWidgetId();
        AppWidgetHostView hostView = mAppWidgetHost.createView(getApplicationContext(), appWidgetId, newAppWidgetProviderInfo);
        hostView.setAppWidget(appWidgetId, newAppWidgetProviderInfo);

        // Add it to your layout
        LinearLayout widgetLayout = view.findViewById(R.id.widget_view);
        widgetLayout.addView(hostView);

        // And bind widget IDs to make them actually work
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            boolean allowed = mAppWidgetManager.bindAppWidgetIdIfAllowed(appWidgetId, newAppWidgetProviderInfo.provider);

            if (!allowed) {
                // Request permission - https://stackoverflow.com/a/44351320/1816603
                Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_BIND);
                intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
                intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER, newAppWidgetProviderInfo.provider);
                final int REQUEST_BIND_WIDGET = 1987;
                startActivityForResult(intent, REQUEST_BIND_WIDGET);
            }
        }

        return true;
    }
}