Passing data from a BroadcastReceiver to MainActivity works correctly only once

六月ゝ 毕业季﹏ 提交于 2019-12-23 05:46:31

问题


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>

回答1:


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);



回答2:


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)




回答3:


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
}


来源:https://stackoverflow.com/questions/4913154/passing-data-from-a-broadcastreceiver-to-mainactivity-works-correctly-only-once

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!