Как отправить параметры из уведомления-клика в активность?

206

Я могу найти способ отправить параметры моей деятельности из моего уведомления.

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

Код из моего сервиса, который создает Уведомление:

        // construct the Notification object.
     final Notification notif = new Notification(R.drawable.icon, tickerText, System.currentTimeMillis());


    final RemoteViews contentView = new RemoteViews(context.getPackageName(), R.layout.custom_notification_layout);
    contentView.setImageViewResource(R.id.image, R.drawable.icon);
    contentView.setTextViewText(R.id.text, tickerText);
    contentView.setProgressBar(R.id.progress,100,0, false);
    notif.contentView = contentView;        

    Intent notificationIntent = new Intent(context, Main.class);
    notificationIntent.putExtra("item_id", "1001"); // <-- HERE I PUT THE EXTRA VALUE
    PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);
    notif.contentIntent = contentIntent;

    nm.notify(id, notif);

Код из моего Activity, который пытается получить дополнительный параметр из уведомления:

 public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.main);


    Bundle extras = getIntent().getExtras();
    if(extras != null){
        Log.i( "dd","Extra:" + extras.getString("item_id") );
    }

Дополнения всегда нулевые, и я никогда ничего не получаю в свой журнал.

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

Любые идеи?

Видар Вестнес
источник

Ответы:

241

Посмотрите это руководство ( создание уведомлений ) и примеры ApiDemos «StatusBarNotifications» и «NotificationDisplay».

Для управления, если действие уже запущено, у вас есть два способа:

  1. Добавьте флаг FLAG_ACTIVITY_SINGLE_TOP в Intent при запуске действия, а затем в классе действия реализуйте обработчик события onNewIntent (намерение) , чтобы вы могли получить доступ к новому намерению, которое было вызвано для действия (которое отличается от простого вызова getIntent). (), это всегда будет возвращать первое намерение, которое запустило вашу деятельность.

  2. То же, что номер один, но вместо добавления флага в Intent вы должны добавить «singleTop» в вашей активности AndroidManifest.xml.

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

Лукас С.
источник
95
и ответить на вопрос пользователя о том, что статистические данные являются нулевыми: вам нужно звонить PendingIntent.getActivity()с флагом PendingIntent.FLAG_UPDATE_CURRENT, в противном случае одни и те же статистические данные будут повторно использоваться для каждого уведомления.
Матиас
2
ты спас мой день, но почему передача простых данных, таких как эта, в Android так сложна
Нелегальный аргумент
8
Если у вас должны быть разные уведомления, обязательно используйте разные идентификаторы запросов при звонке PendingIntent.getActivity()в дополнение к настройкам FLAG_ACTIVITY_SINGLE_TOPна Intentи FLAG_UPDATE_CURRENTна PendingIntent. См stackoverflow.com/questions/7370324/...
schnatterer
101

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

Вот код, который это исправил. Код для создания уведомления о намерениях.

 Intent notificationIntent = new Intent(getApplicationContext(), viewmessage.class);
    notificationIntent.putExtra("NotificationMessage", notificationMessage);
    notificationIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
    PendingIntent pendingNotificationIntent = PendingIntent.getActivity(getApplicationContext(),notificationIndex,notificationIntent,PendingIntent.FLAG_UPDATE_CURRENT);
    notification.flags |= Notification.FLAG_AUTO_CANCEL;
    notification.setLatestEventInfo(getApplicationContext(), notificationTitle, notificationMessage, pendingNotificationIntent);

Код для просмотра сообщения Активность.

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    onNewIntent(getIntent());
}

@Override
public void onNewIntent(Intent intent){
    Bundle extras = intent.getExtras();
    if(extras != null){
        if(extras.containsKey("NotificationMessage"))
        {
            setContentView(R.layout.viewmain);
            // extract the extra-data in the Notification
            String msg = extras.getString("NotificationMessage");
            txtView = (TextView) findViewById(R.id.txtMessage);
            txtView.setText(msg);
        }
    }


}
Мухаммед Юсуф Сулахрия
источник
29

Может быть немного поздно, но: вместо этого:

public void onNewIntent(Intent intent){
    Bundle extras = intent.getExtras();
    Log.i( "dbg","onNewIntent");

    if(extras != null){
        Log.i( "dbg", "Extra6 bool: "+ extras.containsKey("net.dbg.android.fjol"));
        Log.i( "dbg", "Extra6 val : "+ extras.getString("net.dbg.android.fjol"));

    }
    mTabsController.setActiveTab(TabsController.TAB_DOWNLOADS);
}

Использовать это:

Bundle extras = getIntent().getExtras();
if(extras !=null) {
    String value = extras.getString("keyName");
}
pinaise
источник
20
Может быть, опоздал на OP, но никогда не опаздывает на других в Интернете :)
espinchi
19

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

PendingIntent contentIntent = PendingIntent.getActivity(context, **id**, notificationIntent, 0);
notif.contentIntent = contentIntent;
nm.notify(**id**, notif);
jamchen
источник
14

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

как это:

   Intent notificationIntent = new Intent(Main.this, Main.class);
   notificationIntent.putExtra("sport_id", "sport"+id);
   notificationIntent.putExtra("game_url", "gameURL"+id);

   notificationIntent.setData((Uri.parse("foobar://"+SystemClock.elapsedRealtime()))); 

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

Видар Вестнес
источник
8
Anroid повторно использует намерения, действие намерения и код запроса делают его уникальным, но не дополнительные данные. Таким образом, вам нужно установить уникальный идентификатор запроса или использовать другие намеренные действия.
Бачи
10

Я перепробовал все, но ничего не получалось.

в итоге придумали следующее решение.

1- в манифест добавить для активности Android: launchMode = "singleTop"

2 - делая отложенное намерение, сделайте следующее, используйте bundle вместо непосредственного использования intent.putString () или intent.putInt ()

                    Intent notificationIntent = new Intent(getApplicationContext(), CourseActivity.class);

                    Bundle bundle = new Bundle();
                    bundle.putString(Constants.EXAM_ID,String.valueOf(lectureDownloadStatus.getExamId()));
                    bundle.putInt(Constants.COURSE_ID,(int)lectureDownloadStatus.getCourseId());
                    bundle.putString(Constants.IMAGE_URL,lectureDownloadStatus.getImageUrl());

                    notificationIntent.putExtras(bundle);

                    notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP |
                            Intent.FLAG_ACTIVITY_SINGLE_TOP);
                    PendingIntent contentIntent = PendingIntent.getActivity(getApplicationContext(),
                            new Random().nextInt(), notificationIntent,
                            PendingIntent.FLAG_UPDATE_CURRENT); 
Дирадж Сашан
источник
3
Меня устраивает. Необходимо использовать другое значение requestCode и флаг PendingIntent.FLAG_UPDATE_CURRENT.
phuongle
4

AndroidManifest.xml

Включить launchMode = "singleTop"

<activity android:name=".MessagesDetailsActivity"
        android:launchMode="singleTop"
        android:excludeFromRecents="true"
        />

SMSReceiver.java

Установите флаги для Intent и PendingIntent

Intent intent = new Intent(context, MessagesDetailsActivity.class);
    intent.putExtra("smsMsg", smsObject.getMsg());
    intent.putExtra("smsAddress", smsObject.getAddress());
    intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);

    PendingIntent contentIntent = PendingIntent.getActivity(context, notification_id, intent, PendingIntent.FLAG_UPDATE_CURRENT);

MessageDetailsActivity.java

onResume () - вызывается каждый раз, загружает дополнения.

Intent intent = getIntent();
    String extraAddress = intent.getStringExtra("smsAddress");
    String extraBody = intent.getStringExtra("smsMsg");

Надеюсь, это поможет, это было основано на других ответах здесь на stackoverflow, но это наиболее обновленный, который работал для меня.

Мигель Хесус
источник
3

Это просто, это мое решение с использованием объектов!

МОЙ ПОЖО

public class Person implements Serializable{

    private String name;
    private int age;

    //get & set

}

Метод уведомления

  Person person = new Person();
  person.setName("david hackro");
  person.setAge(10);

    Intent notificationIntent = new Intent(this, Person.class);
    notificationIntent.putExtra("person",person);
    notificationIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);

NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.mipmap.notification_icon)
                .setAutoCancel(true)
                .setColor(getResources().getColor(R.color.ColorTipografiaAdeudos))
                .setPriority(2)
                .setLargeIcon(bm)
                .setTicker(fotomulta.getTitle())
                .setContentText(fotomulta.getMessage())
                .setContentIntent(PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT))
                .setWhen(System.currentTimeMillis())
                .setContentTitle(fotomulta.getTicketText())
                .setDefaults(Notification.DEFAULT_ALL);

Новая активность

 private Person person;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_notification_push);
    person = (Person) getIntent().getSerializableExtra("person");
}

Удачи!!

Дэвид Хакро
источник
3

После некоторого поиска я получил решение от руководства разработчика Android

PendingIntent contentIntent ;
Intent intent = new Intent(this,TestActivity.class);
intent.putExtra("extra","Test");
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);

stackBuilder.addParentStack(ArticleDetailedActivity.class);

contentIntent = stackBuilder.getPendingIntent(0,PendingIntent.FLAG_UPDATE_CURRENT);

Чтобы получить дополнительное значение Intent в классе Test Activity, вам нужно написать следующий код:

 Intent intent = getIntent();
 String extra = intent.getStringExtra("extra") ;
Мохит
источник
3
Для чего stackBuilder?
AlexioVay
1

В своей реализации уведомлений используйте код, подобный следующему:

NotificationCompat.Builder nBuilder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID);
...
Intent intent = new Intent(this, ExampleActivity.class);
intent.putExtra("EXTRA_KEY", "value");

PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
nBuilder.setContentIntent(pendingIntent);
...

Чтобы получить Intent дополнительные значения в ExampleActivity, используйте следующий код:

...
Intent intent = getIntent();
if(intent!=null) {
    String extraKey = intent.getStringExtra("EXTRA_KEY");
}
...

ОЧЕНЬ ВАЖНОЕ ПРИМЕЧАНИЕ: метод Intent :: putExtra () перегружен . Чтобы получить дополнительный ключ, вам нужно использовать метод Intent :: get [Type] Extra () .

Примечание: NOTIFICATION_ID и NOTIFICATION_CHANNEL_ID являются константами, объявленными в ExampleActivity

Карлос Эспиноза
источник
1

Я тоже могу сказать, что перепробовал все, что упоминалось в этих постах, и еще несколько из других. Проблема № 1 для меня заключалась в том, что новый Intent всегда имел нулевой пакет. Моя проблема заключалась в том, чтобы сосредоточиться слишком много на деталях «я включил .this или .that». Мое решение состояло в том, чтобы сделать шаг назад от деталей и рассмотреть общую структуру уведомления. Когда я сделал это, мне удалось разместить ключевые части кода в правильной последовательности. Итак, если у вас возникли похожие проблемы, проверьте:

1. Intent notificationIntent = new Intent(MainActivity.this, NotificationActivity.class);

2a. Bundle bundle = new Bundle();

// Мне больше нравится указывать тип данных. например, bundle.putInt

2b. notificationIntent.putExtras(bundle);
3. PendingIntent contentIntent = PendingIntent.getActivity(MainActivity.this, WIZARD_NOTIFICATION_ID, notificationIntent,
                    PendingIntent.FLAG_UPDATE_CURRENT);
notificationIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
4. NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
5.          NotificationCompat.Builder nBuilder =
                    new NotificationCompat.Builder(this)
                            .setSmallIcon(R.drawable.ic_notify)
                            .setContentTitle(title)
                            .setContentText(content)
                            .setContentIntent(contentIntent)
                            .setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE)
                            .setAutoCancel(false)//false is standard. true == automatically removes the notification when the user taps it.
                            .setColor(getResources().getColor(R.color.colorPrimary))
                            .setCategory(Notification.CATEGORY_REMINDER)
                            .setPriority(Notification.PRIORITY_HIGH)
                            .setVisibility(NotificationCompat.VISIBILITY_PUBLIC);
            notificationManager.notify(WIZARD_NOTIFICATION_ID, nBuilder.build());

С этой последовательностью я получаю правильный пакет.

Питер Сутер
источник
0

Если вы используете

android:taskAffinity="myApp.widget.notify.activity"
android:excludeFromRecents="true"

в файле AndroidManifest.xml для запуска действия необходимо использовать следующее в своем намерении:

Intent notificationClick = new Intent(context, NotifyActivity.class);
    Bundle bdl = new Bundle();
    bdl.putSerializable(NotifyActivity.Bundle_myItem, myItem);
    notificationClick.putExtras(bdl);
    notificationClick.setData(Uri.parse(notificationClick.toUri(Intent.URI_INTENT_SCHEME) + myItem.getId()));
    notificationClick.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);  // schließt tasks der app und startet einen seperaten neuen

    TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
    stackBuilder.addParentStack(NotifyActivity.class);
    stackBuilder.addNextIntent(notificationClick);

    PendingIntent notificationPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
    mBuilder.setContentIntent(notificationPendingIntent);

Важно установить уникальные данные, например, используя уникальный идентификатор, например:

notificationClick.setData(Uri.parse(notificationClick.toUri(Intent.URI_INTENT_SCHEME) + myItem.getId()));
попрошайка
источник
0

Пожалуйста, используйте как PendingIntent при отображении уведомления, чем оно будет разрешено.

PendingIntent intent = PendingIntent.getActivity (this, 0 ,tificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);

Добавьте PendingIntent.FLAG_UPDATE_CURRENT в качестве последнего поля.

M.Noman
источник