Подтвердить что ты не робот

Добавление виджетов на страницу запуска без bindAppWidgetId()

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

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

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

4b9b3361

Ответ 1

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

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

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

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

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

Ответ 2

Timmmm,

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

EDIT: дополнительный фон в процессе привязки виджета

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

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

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

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

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

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

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

AppWidgetHost myHost = new AppWidgetHost(context, SOME_NUMERICAL_CONSTANT_AS_AN_ID);

Теперь получите свой 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()

Подводя итоги

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

EDIT: окончательное уточнение

Также запускается ICS Launcher. Используемые AppWidgetManager - это всего лишь оболочка, содержащая AppWidgetHost и вызовы AppWidgetManager. Я забыл, что об этом очень мало говорится на веб-сайте Android Development Central.

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

FuzzicalLogic

Ответ 3

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

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

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

Приветствия,
Yuvi

Ответ 4

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 ничего не создает.