2

I have created a test Android launcher application and installed it on a rooted device as a system app. The goal is for the app to place all installed widgets on fragments of a viewpager. This has been successfully accomplished; however, the user is shown a message every time a new page is shown.

no description

Even if the user checks the box, the message is still shown every time a widget is to be added.

I have generally followed the steps in Hosting widgets in an android launcher and Adding widgets to a launcher page without bindAppWidgetId() to add widgets to the app.

First I get a list of widgets in the class that extends application and store it in a public static variable

AppWidgetManager manager = AppWidgetManager.getInstance(this); 
widgetList = manager.getInstalledProviders();

Next I use a bind intent to get the widget

appWidgetManager = AppWidgetManager.getInstance(this.getActivity());
appWidgetHost = new AppWidgetHost(this.getActivity(), APPWIDGET_HOST_ID);
int id = appWidgetHost.allocateAppWidgetId();
Intent bindIntent = new Intent(AppWidgetManager.ACTION_APPWIDGET_BIND);
bindIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, id);
bindIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER,LauncherExperiment.widgetList.get(mParam1).provider);
startActivityForResult(bindIntent, REQUEST_BIND_APPWIDGET);

Then on activity result I create the widget

Bundle extras = data.getExtras();
int appWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);
AppWidgetProviderInfo appWidgetInfo = appWidgetManager.getAppWidgetInfo(appWidgetId);

AppWidgetHostView hostView = appWidgetHost.createView(this.getActivity(), appWidgetId, appWidgetInfo);
hostView.setAppWidget(appWidgetId, appWidgetInfo);
// Add  it on the layout you want
myLayout.addView(hostView);

Again, I have rooted the device and installed the app as a system app by updating the manifest

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.test.launcherexperiment"
android:sharedUserId="android.uid.system" >

And by following the steps here: How can I sign my application with the system signature key?

So in summary, I have been able to successfully bind apps and display them; but the issue is that the warning message should be displayed at most one time.

Community
  • 1
  • 1

1 Answers1

3

Here we go! With this code the user will only be shown the dialog once. It also shows a complete solution for adding widgets programmatically.

As I will be updating this on my github, look here for the latest version, https://github.com/DagW/FragmentHomescreen/blob/master/app/src/main/java/se/dw/fragmenthomescreen/widget/WidgetFragment.java.

But for archiving purposes here is the way I do it now.

/**
 * checkToAddWidget
 * <p/>
 * At the creation of WidgetFragment,
 * add a default widget so that the homescreen is not empty
 * shows how to add widgets programmatically
 */
private void checkToAddWidget () {
        MainActivity m = (MainActivity) getActivity();
        AppWidgetManager manager = m.getAppWidgetManager();
        AppWidgetHost host = m.getAppWidgetHost();

        List<AppWidgetProviderInfo> widgetList = manager.getInstalledProviders();

        AppWidgetProviderInfo searchProvider = null;
        AppWidgetProviderInfo search2Provider = null;
        AppWidgetProviderInfo clockProvider = null;

        for ( AppWidgetProviderInfo info : widgetList ) {
            Log.d(TAG, info.provider.getPackageName() + " " + info.provider.getClassName());
            if ( info.provider.getClassName().equals("com.google.android.googlequicksearchbox.SearchWidgetProvider") ) {
                searchProvider = info;
                break;
            }
            if ( info.provider.getClassName().equals("com.android.alarmclock.AnalogAppWidgetProvider") ) {
                clockProvider = info;
            }
            if ( info.provider.getClassName().equals("com.android.alarmclock.DigitalAppWidgetProvider") ) {
                clockProvider = info;
            }
            if ( info.provider.getClassName().equals("com.android.quicksearchbox.SearchWidgetProvider") ) {
                search2Provider = info;
            }
        }
        if ( searchProvider != null || search2Provider != null || clockProvider != null ) {
            AppWidgetProviderInfo provider = null;
            if ( searchProvider != null ) {
                provider = searchProvider;
            } else if ( clockProvider != null ) {
                provider = clockProvider;
            } else {
                provider = search2Provider;
            }

            addProvider(m, host, manager, provider);
        }
    }



public void addProvider (MainActivity m, AppWidgetHost host, AppWidgetManager manager, AppWidgetProviderInfo provider) {
    int id = host.allocateAppWidgetId();
    boolean success = false;
    success = manager.bindAppWidgetIdIfAllowed(id, provider.provider);

    if ( success ) {
        AppWidgetHostView hostView = host.createView(getActivity(), id, provider);
        AppWidgetProviderInfo appWidgetInfo = manager.getAppWidgetInfo(id);

        LauncherAppWidgetInfo info = new LauncherAppWidgetInfo(id);
        info.setHostView(hostView);
        info.getHostView().setAppWidget(id, appWidgetInfo);

        ItemInfo launcherInfo = attachWidget(info);
        if ( launcherInfo != null ) {
            WidgetPersistance.addDesktopAppWidget(screen, launcherInfo);
        }

    } else {
        Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_BIND);
        intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, id);
        intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER, provider.provider);
        m.startActivityForResult(intent, MainActivity.REQUEST_BIND_APPWIDGET);
    }

}

You might also need

<uses-permission android:name="android.permission.BIND_APPWIDGET"
                 tools:ignore="ProtectedPermissions"/>
DagW
  • 955
  • 1
  • 15
  • 28
  • That permission is only available to system apps. In your app it is not doing anything. Unless you are expecting the user to become root and convert your app to a system one. – Jose Gómez Dec 06 '17 at 11:13
  • This is very close to the solution that I have arrived to. Do you also have the issue when if you click on the widget and the associated app opens, once you click back your whole app closes? (Instead of going back to your app) – Jose Gómez Dec 06 '17 at 11:15
  • And actually, weird thing, I need to have that permission even though it is as you say. Maybe after you have been selected as default launcher its given? – DagW Mar 12 '18 at 18:48