Добавление виджетов на страницу запуска без bindAppWidgetId () - PullRequest
19 голосов
/ 17 марта 2012

Я пытаюсь превратить стандартную программу запуска ICS в отдельное приложение.Я почти у цели - единственное, что не работает, это значок поиска и сброс виджетов на экран, что приводит к сбою.

Сбой в том, что в стандартной программе запуска appWidgetManager.bindAppWidgetId(appWidgetId, componentName); используются для добавления виджетов, которые очевидно, только системные приложения имеют разрешение на выполнение .

Так что мой вопрос в том, как правильно для несистемного приложения добавлять виджеты и получать те же возможности пользовательского интерфейса, что и дляфондовая пусковая установка ICS ?

Ответы [ 4 ]

12 голосов
/ 20 марта 2012

Timmmm,

Ваша проблема в том, что вы смотрите не на тот объект.Вы не можете реально контролировать AppWidgetManager.Это не ваша работа, а система.То, что вы МОЖЕТЕ сделать, это управлять AppWidgetHost, просто требуется немного семантики.Вот основные сведения.

РЕДАКТИРОВАТЬ: дополнительный фон в процессе привязки виджета

AppWidgetManager - это одноэлементный объект, который запускается при запуске системы.Это означает, что каждый экземпляр каждого модуля запуска использует один и тот же AppWidgetManager.То, что отличает их, является их AppWidgetHost и RemoteViews, которые они в настоящее время имеют.AppWidgetManager в основном хранит список всех активных хостов и виджетов, которые они содержат.AppWidgetHost не является привилегированным объектом.То есть любая деятельность может иметь один хост.Таким образом, целое приложение может быть только виджетами, если они того пожелают.

Когда вы создаете экземпляр Host, вы должны затем добавить Views к нему.Итак, в основном это список дочерних представлений без обязательных родительских границ, за исключением того, что дает ваша активность.Сначала вы запрашиваете ID (через myHost.allocateAppWidgetId()).Затем вы используете свою активность / диалог выбора виджета.Диалог возвращает WidgetInfo.Вид восстанавливается, когда вы запрашиваете у хоста создать представление (через createView) с помощью WidgetInfo и идентификатора, который вы запрашивали.Затем он запрашивает у виджета его RemoteView.

Наконец, вы связываете виджет, помещая представление в свою деятельность в качестве дочернего элемента.Это делается с помощью метода addView () ViewGroup, который содержит все ваши виджеты.

Процесс в действии (EDITED)

Во-первых, у вас естьчтобы убедиться, что у вас есть это в вашем манифесте андроида:

<uses-permission android:name="android.permission.BIND_APPWIDGET" />

Далее, вам нужно создать AppWidgetHost (я расширяю свой собственный для своей программы запуска).Ключ к Хосту - сохранить ссылку на AppWidgetManager через AppWidgetManager.getInstance();.

AppWidgetHost myHost = new AppWidgetHost(context, SOME_NUMERICAL_CONSTANT_AS_AN_ID);

Теперь получите свой идентификатор:

myHost.allocateAppWidgetId()

Следующий шаг выполняется любым способом, который вы используете для получения информации о виджете.В большинстве случаев он возвращается через Intent через onActivityResult.Теперь все, что вам действительно нужно сделать, это использовать appInfo и создать представление.WidgetId обычно предоставляется результатом активности виджета выбора.

AppWidgetProviderInfo withWidgetInfo 
        = AppWidgetManager.getInstance().getAppWidgetInfo(forWidgetId);
AppWidgetHostView hostView 
        = myWidgetHost.createView(myContext, forWidgetId, withWidgetInfo);
hostView.setAppWidget(forWidgetId, withWidgetInfo);

Теперь вы просто привязываете View как ребенок к тому, с чем хотите связать его.

myViewGroup.addView(hostView);

Конечно, вы всегда должны учитывать, где и как его разместить.и т. д. Кроме того, вы должны убедиться, что ваш AppWidgetHost прослушивает, прежде чем начать добавлять виджеты.

myHost.startListening()

Для суммирования

Процесс привязки виджета охватывает множество методов и этапов, но все происходит через AppWidgetHost.Поскольку виджеты закодированы вне вашего пространства имен, у вас нет никакого контроля, кроме того, где вы их размещаете и как вы изменяете размер представления.Поскольку в конечном итоге они представляют собой код, выполняемый в вашем пространстве, но вне вашего контроля, AppWidgetManager действует как нейтральный посредник, а AppWidgetHost выступает в качестве посредника от имени вашего приложения.Как только это поняли, ваша задача проста.Вышеуказанные шаги - это все необходимые шаги для любого пользовательского модуля запуска (включая мой собственный).

РЕДАКТИРОВАТЬ: окончательное уточнение

Модуль запуска ICS делает это такжеappWidgetManager, который они используют, это просто оболочка для AppWidgetHost и звонки на AppWidgetManager.Я забыл, что это очень мало объясняется на веб-сайте Android Development Central.

Надеюсь, это поможет!Дайте мне знать, если вам нужно больше деталей.

FuzzicalLogic

8 голосов
/ 24 июля 2012

Теперь я знаю окончательный ответ.В Android 4.0 вы не можете сделать это.Я закончил тем, что заставил моих пользователей выбирать виджет дважды, что отстой, но у него нет пути.

В Android 4.1 они исправили проблему!

SDK-приложенияТеперь можно размещать виджеты и не использовать API для выбора виджетов мусора!Вы можете посмотреть подробности в исходном коде Jellybean Launcher2, но в основном, когда вы впервые пытаетесь связать виджет, в Android появится диалоговое окно с надписью «Хотите ли вы разрешить этому приложению связывать виджеты», а затем пользовательрешили дать ему разрешение или нет.

Я не уверен, почему они выбрали модальное диалоговое окно предоставления разрешений, а не модель "все права на установку", которую они использовали для всего остального, ночто угодно, это работает!

Теперь нам осталось подождать 4 или 5 лет, пока у всех не будет Android 4.1 или выше!

4 голосов
/ 27 марта 2012

Я только что нашел этот учебник о том, как добавить appwidgets в обычные приложения, что может помочь: http://coderender.blogspot.com/2012/01/hosting-android-widgets-my.html

В этом учебнике все еще используется список "AppWidget Picker", поэтому он может не работать у вас, так как ICSимеет средство выбора виджетов внутри самого ящика приложения.

Тем не менее, стоит упомянуть, поскольку учебники по размещению виджетов очень редки:)

Cheers,Yuvi

2 голосов
/ 11 августа 2012

Fuzzical Logic, с вашим кодом ниже,

AppWidgetProviderInfo withWidgetInfo 
        = AppWidgetManager.getInstance().getAppWidgetInfo(forWidgetId);
AppWidgetHostView hostView 
        = myWidgetHost.createView(myContext, forWidgetId, withWidgetInfo);
hostView.setAppWidget(forWidgetId, withWidgetInfo);

, если у вас нет разрешения bind_widget, widgethost ничего не получил , cus withwidgetinfo имеет значение null, widgethost ничего не создает.

...