Передача данных из виджета в приложение

Я разрабатываю виджет для своего приложения и хочу передать определенные данные из виджета в приложение. Пользователь может добавить несколько версий виджета, и мне нужно определить, из какого виджета он исходит, чтобы я мог отображать конкретную информацию в приложении.

То, что у меня есть, работает до сих пор, но только если я полностью выхожу из своего приложения (неоднократно нажимая кнопку «Назад»), в противном случае оно, похоже, не обнаруживает передаваемые данные.

Этот код я должен передать данные из виджета в приложение:

public class WidgetProvider extends AppWidgetProvider  {

    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {

        final int N = appWidgetIds.length;

        for (int i=0; i<N; i++) 
            UpdateWidget(context, appWidgetManager, appWidgetIds[i]);
    }

    public static void UpdateWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId)
    {
        Intent intent = new Intent(context, Main.class);
        final Bundle bun = new Bundle();
        bun.putInt("widgetId", appWidgetId);
        intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
        intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.putExtras(bun);

        PendingIntent pendingIntent = PendingIntent.getActivity(context, appWidgetId, intent, PendingIntent.FLAG_UPDATE_CURRENT);

        RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget);
        views.setOnClickPendingIntent(R.id.widgetText, pendingIntent);

        appWidgetManager.updateAppWidget(appWidgetId, views);
    }
}

ОБНОВЛЕНИЕ

Приближаемся к тому, чтобы это заработало, благодаря Талу Канелю. У меня есть ActionBar в моем приложении, и, следуя рекомендациям Google, у меня есть этот код в onOptionsItemSelected:

if (item.getItemId() == android.R.id.home) {
          final Intent intent = new Intent(activity, Main.class);
          intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
          startActivity(intent);
          return true;
    } 

Если я нажму кнопку «Назад» в ActionBar, затем сверну свое приложение и нажму на виджет, этот код всегда будет нулевым:

    if (getIntent().getExtras() != null)
    {

    }

ОБНОВЛЕНИЕ 2

На самом деле, простое возвращение к основному действию в моем приложении приводит к тому, что getExtras() становится нулевым. У меня есть этот код в моем виджете приложения, который не передает никаких дополнений в приложение:

    PendingIntent piMain = PendingIntent.getActivity(context, appWidgetId, new Intent(context, Main.class), PendingIntent.FLAG_UPDATE_CURRENT);

    rv.setOnClickPendingIntent(R.id.widgetTitle, piMain);

Если я нажму на эту часть в своем виджете, а затем вернусь и нажму на часть моего виджета, которая должна передавать дополнительные функции, getExtras() всегда будет нулевым.


person Kris B    schedule 07.07.2012    source источник


Ответы (1)


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

о вашей проблеме:
вы пытаетесь запустить активность из виджета с флагом FLAG_ACTIVITY_CLEAR_TOP, вот его определение:

Если установлено, и запускаемое действие уже выполняется в текущей задаче, то вместо запуска нового экземпляра этого действия все другие действия поверх него будут закрыты, и это намерение будет доставлено в (сейчас на вверху) старая деятельность как новое намерение.

это означает, что если ваша основная активность уже запущена на переднем плане, то при запуске активности из виджета все другие активности поверх этой основной активности будут удалены из стека, а основная активность возобновится и попадет в активность. onNewIntent(намерение) обратный вызов.

вот почему вы не видите данные - потому что активность не перезапускается с новым намерением, а только попадает в onNewIntent (намерение) с новым отправленным вами намерением.

Я уверен, что если вы поставите точку останова в методе onNewIntent(intent) - вы увидите, что отправленное вами намерение доставляется туда со всеми дополнительными данными.

еще одна проблема с вашим кодом: проверьте определение метода Intent.putExtras(boundle):

Добавьте в намерение набор расширенных данных. Ключи должны включать префикс пакета, например, приложение com.android.contacts будет использовать такие имена, как «com.android.contacts.ShowAll».

похоже, вы не называете свой префикс ключа в соответствии с правилами. поэтому он нулевой.

надеюсь, это помогло вам.

person Tal Kanel    schedule 13.07.2012
comment
Спасибо за ответ. Это первый виджет приложения, который я создал, поэтому я все еще во всем разбираюсь. Вы правы, onNewItent получает удар, поэтому я добавил туда свой код для проверки наличия дополнений, и, похоже, он работает, но только после второго нажатия на виджет. - person Kris B; 13.07.2012
comment
@KrisB: именно так и должно было случиться - если активность не в стеке (в первый раз), то данные получены обычным способом - через onCreate() и getIntent(), а в остальные моменты (когда активность уже внутри стека), вы получите намерение, бросившее onNewIntent() - person Tal Kanel; 13.07.2012
comment
Вы правы, именно так это и работает. У меня есть проверка дополнительных функций как в onCreate, так и в onNewIntent, проблема, похоже, в том, что когда я использую if (getIntent().getExtras() != null), иногда getExtras() становится null. Я ожидал, что getExtras() никогда не будет null при нажатии из виджета. - person Kris B; 13.07.2012
comment
Посмотрите код, который я добавил в OP. У меня есть раздел моего виджета, который не пропускает никаких дополнений, и основной раздел, который пропускает. Если я нажму на раздел, который не передает никаких дополнений, а затем вернусь к виджету и нажму на раздел, который это делает, getExtras() всегда будет нулевым. - person Kris B; 13.07.2012
comment
@KrisB: я обновил свой ответ. Я думаю, что нашел, почему он был нулевым. это объяснило дополнение к ответу - person Tal Kanel; 14.07.2012
comment
Неудачно. Я добавил имя пакета к дополнительным именам ключей, и в первый раз оно всегда равно нулю. Очень странный. - person Kris B; 14.07.2012
comment
Я думаю, что у меня это так близко, как я собираюсь получить его. Для 99% людей, использующих виджет, он, вероятно, будет работать так, как ожидалось, поэтому для второстепенных пользователей это не стоит времени/усилий. Спасибо за вашу помощь. - person Kris B; 14.07.2012
comment
@KrisB: действительно странно. но я могу дать вам последний совет, который, возможно, может решить эту странную проблему: вместо того, чтобы ставить бандл с методом putExtras(), используйте намерение.putExtra(widgetId, id), а при попытке получить его в действии используйте метод int widgetId = намерение.getIntExtra(widgetId, значение по умолчанию). в конце концов - вам действительно не нужен пакет, а только одно единственное значение. - person Tal Kanel; 14.07.2012
comment
@Tal Это не работает. В вашем сценарии будут вызываться только onCreate(), onStart() и onResume(). onNewIntent() будет вызываться только в том случае, если вы активируете намерение из действия, а НЕ ИЗ ВИДЖЕТА. - person IgorGanapolsky; 29.10.2012
comment
@IgorG.: если вы запустите намерение с помощью FLAG_ACTIVITY_SINGLE_TOP, и ранее вы отклонили действие, нажав кнопку «Домой», чтобы уйти от него (а не кнопку «Назад»), и система еще не уничтожила ваше действие для сохраняя память, он вернется к обратному вызову onNewIntent() и вернется на передний план. даже из виджета - person Tal Kanel; 29.10.2012