将数据从 BroadcastReceiver 传递到 MainActivity 只能正确运行一次

发布于 2024-10-16 05:57:09 字数 4252 浏览 2 评论 0原文

我有一个 PushNotificationReceiver(扩展 BroadcastReceiver)MainActivity。接收方通过 IntentMainActivity 发送一些数据(例如字符串值“New value”)。然后,MainActivity 使用此值更新其 TextView。 在我将此 TextView 值更改为其他值(例如将其重置为“UNSPECIFIED”)并将 Activity 移至后台并再次移至前台之前,此方法工作正常。 MainActivity 已恢复,其 TextView 包含“新值”,但我预计它是“UNSPECIFIED” - 这就是问题

我的应用程序出了什么问题?

整个原型项目可以在此处下载。

这是我的 MainActivity 代码

private TextView tvValue;
private EditText etNewValue;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    tvValue = (TextView)findViewById(R.id.value);
    etNewValue = (EditText)findViewById(R.id.new_value);

    findViewById(R.id.reset).setOnClickListener(new OnClickListener() {         
        @Override
        public void onClick(View v) {
            tvValue.setText(getResources().getString(R.string.not_specified));
        }
    });

    findViewById(R.id.send_notification).setOnClickListener(new OnClickListener() {         
        @Override
        public void onClick(View v) {
            sendNotification(etNewValue.getText().toString());
        }
    });

    processDataFromBroadcast(getIntent());        
}

@Override
public void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    processDataFromBroadcast(intent);
}

private void sendNotification(String value){
    NotificationManager mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

    String title = "Proto App Notif";

    Notification notification = new Notification(
            android.R.drawable.ic_notification_overlay,
            title,
            System.currentTimeMillis());
    notification.flags |= Notification.FLAG_AUTO_CANCEL;

    Context ctxApp = getApplicationContext();

    Intent notificationIntent = new Intent()
        .setAction(PushNotificationReceiver.ACTION_NOTIFICATION)
        .putExtra("value", value);
    PendingIntent contentIntent = PendingIntent.getBroadcast(
            ctxApp, 
            0, 
            notificationIntent, 
            PendingIntent.FLAG_UPDATE_CURRENT);     

    notification.setLatestEventInfo(
            ctxApp,
            title,
            value,
            contentIntent);

    notification.audioStreamType = AudioManager.STREAM_NOTIFICATION;

    mNotificationManager.notify(1, notification);           
}

private void processDataFromBroadcast(Intent intent) {
    if (!intent.hasExtra("value")){
        return;
    }

    String val = intent.getStringExtra("value");

    tvValue.setText(val); // Updating my activity look
}

PushNotificationReceiver

private static final String LOG_CAT = "PushNotificationReceiver";
static final String ACTION_NOTIFICATION = "com.mobiwolf.proto.NOTIFICATION_RECEIVER";

@Override
public void onReceive(Context context, Intent intent) {
    if (!intent.getAction().equals(ACTION_NOTIFICATION)) {
        return;
    }

    String value = intent.getStringExtra("value");

    Log.d(LOG_CAT, "Received notification message: "+value); // Log always contains the value sent on first time

    Intent i = new Intent();
    i.setClass(context, MainActivity.class);
    i.putExtra("value", value);
    i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

    context.startActivity(i);
}

和清单

    <receiver android:name="com.mobiwolf.proto.PushNotificationReceiver">
        <intent-filter>
            <action android:name="com.mobiwolf.proto.NOTIFICATION_RECEIVER" />
        </intent-filter>
    </receiver>    

    <activity android:name=".MainActivity"
              android:label="@string/app_name"
              android:launchMode="singleTask">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

I have a PushNotificationReceiver (extends BroadcastReceiver) and MainActivity. The receiver sends some data (for example string value "New value") to the MainActivity via an Intent. Then MainActivity updates its TextView with this value.
This works fine until I change this TextView value to some other value (for example reset it to "UNSPECIFIED") and move the activity to background and to foreground again. The MainActivity is restored and its TextView contains "New value", however I expected it to be "UNSPECIFIED" - this is the problem.

What is wrong with my app?

The whole proto project may be downloaded here.

Here is my MainActivity code

private TextView tvValue;
private EditText etNewValue;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    tvValue = (TextView)findViewById(R.id.value);
    etNewValue = (EditText)findViewById(R.id.new_value);

    findViewById(R.id.reset).setOnClickListener(new OnClickListener() {         
        @Override
        public void onClick(View v) {
            tvValue.setText(getResources().getString(R.string.not_specified));
        }
    });

    findViewById(R.id.send_notification).setOnClickListener(new OnClickListener() {         
        @Override
        public void onClick(View v) {
            sendNotification(etNewValue.getText().toString());
        }
    });

    processDataFromBroadcast(getIntent());        
}

@Override
public void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    processDataFromBroadcast(intent);
}

private void sendNotification(String value){
    NotificationManager mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

    String title = "Proto App Notif";

    Notification notification = new Notification(
            android.R.drawable.ic_notification_overlay,
            title,
            System.currentTimeMillis());
    notification.flags |= Notification.FLAG_AUTO_CANCEL;

    Context ctxApp = getApplicationContext();

    Intent notificationIntent = new Intent()
        .setAction(PushNotificationReceiver.ACTION_NOTIFICATION)
        .putExtra("value", value);
    PendingIntent contentIntent = PendingIntent.getBroadcast(
            ctxApp, 
            0, 
            notificationIntent, 
            PendingIntent.FLAG_UPDATE_CURRENT);     

    notification.setLatestEventInfo(
            ctxApp,
            title,
            value,
            contentIntent);

    notification.audioStreamType = AudioManager.STREAM_NOTIFICATION;

    mNotificationManager.notify(1, notification);           
}

private void processDataFromBroadcast(Intent intent) {
    if (!intent.hasExtra("value")){
        return;
    }

    String val = intent.getStringExtra("value");

    tvValue.setText(val); // Updating my activity look
}

PushNotificationReceiver

private static final String LOG_CAT = "PushNotificationReceiver";
static final String ACTION_NOTIFICATION = "com.mobiwolf.proto.NOTIFICATION_RECEIVER";

@Override
public void onReceive(Context context, Intent intent) {
    if (!intent.getAction().equals(ACTION_NOTIFICATION)) {
        return;
    }

    String value = intent.getStringExtra("value");

    Log.d(LOG_CAT, "Received notification message: "+value); // Log always contains the value sent on first time

    Intent i = new Intent();
    i.setClass(context, MainActivity.class);
    i.putExtra("value", value);
    i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

    context.startActivity(i);
}

And manifest

    <receiver android:name="com.mobiwolf.proto.PushNotificationReceiver">
        <intent-filter>
            <action android:name="com.mobiwolf.proto.NOTIFICATION_RECEIVER" />
        </intent-filter>
    </receiver>    

    <activity android:name=".MainActivity"
              android:label="@string/app_name"
              android:launchMode="singleTask">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

筱果果 2024-10-23 05:57:09

替换

i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

i.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | 
    Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);

Replace

i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

by

i.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | 
    Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
一笑百媚生 2024-10-23 05:57:09

为了解决这个问题,我添加了全局静态触发器

  /**
  * This class triggers whether pushnotification was handled by MainActivity
  * (Preventing handling this push notification twice when the MainActivity 
  * is moved to background and restored from background
  */
  public final class PushNotifHandledTrigger {
private static boolean handled = true;

public static boolean wasHandled(){
    return handled;
}

public static void set(){
    handled = true;
}

public static void reset(){
    handled = false;
}
  }

然后在startActivity之前我重置了这个触发器并在处理后设置(当然,仅在未设置触发器时才执行处理)

For solving this problem I added global static trigger

  /**
  * This class triggers whether pushnotification was handled by MainActivity
  * (Preventing handling this push notification twice when the MainActivity 
  * is moved to background and restored from background
  */
  public final class PushNotifHandledTrigger {
private static boolean handled = true;

public static boolean wasHandled(){
    return handled;
}

public static void set(){
    handled = true;
}

public static void reset(){
    handled = false;
}
  }

Then before startActivity I do reset this trigger and set after handling (and of course perform handling only if trigger is not set)

千纸鹤带着心事 2024-10-23 05:57:09

定义一个 public static boolean newUpdate; 变量,在 context.startActivity(i); 之前将其设置为 true。然后,当您在 MainActivity 中检查意图是否有 extra 时,还要验证 newUpdate 是否为 true >,如果是,请将其重置为 false 并更新您的 TextView 字段。最后一个函数将如下所示

private void processDataFromBroadcast(Intent intent) {
   if ( !intent.hasExtra("value") || (newUpdate == false) ){ //So only new updates are processed.
      return;
   }
   newUpdate = false; //This action will not be repeated unless another notification arrives
   String val = intent.getStringExtra("value");

   tvValue.setText(val); // Updating my activity look
}

Define a public static boolean newUpdate; variable, set it to true right before context.startActivity(i);. Then, when in your MainActivity you check to see the intent has extra with it, also verify that newUpdate is true, and if it is, reset it to false and update your TextView field. The last function will look like this

private void processDataFromBroadcast(Intent intent) {
   if ( !intent.hasExtra("value") || (newUpdate == false) ){ //So only new updates are processed.
      return;
   }
   newUpdate = false; //This action will not be repeated unless another notification arrives
   String val = intent.getStringExtra("value");

   tvValue.setText(val); // Updating my activity look
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文