2011-07-16 17 views
2

我有一個服務,就此討論而言,持有一個數字和一個字符串以呈現給一個活動。把它看作一個面向服務的複製緩衝區。啓動後,服務開始(使用startService)如下:服務的Intent.replaceExtras(捆綁)不能按預期工作

Intent srvIntent = new Intent(this, SetManager.class); 
Bundle bundle = new Bundle(); 
bundle.putLong(getString(R.string.intent_key_setnbr), setNbr); 
bundle.putString(getString(R.string.intent_key_setmsg), setMsg); 
srvIntent.putExtras(bundle); 
startService(srvIntent); 
return true; 

所有工作正常。服務啓動,在通知中顯示由setMsg標識的消息(例如「MESSAGE1」)。

當用戶觸摸通知時,會啓動一個活動,並且該活動會更新setNbr和setMsg,並將其發送回服務。服務依次用新消息更新通知,例如, 「MESSAGE2」(也可以正常工作)。

但是,這裏有一些問題:當用戶觸摸這個通知時,原始setMsg(「MESSAGE1」)就是Activity所顯示的內容,而不是「MESSAGE2」。我已經放入Log.d()的東西來查看進程出錯的地方,但我沒有看到它。服務記錄傳入的「MESSAGE2」就好了,並在replaceExtras()後點擊代碼。實際上,傳入的值必須是正確的,否則Notification將不會更新爲「MESSAGE2」。因此,Notification Intent的額外套件似乎沒有正確更新,因爲所有其他往返行爲都可以正常工作。或者,不太可能,該活動僅在第一次嘗試時才能正常工作?

所以我質疑我的方法來更新通知。我相信它是「靠書本」,但作爲一個相對的android新手,還有很多我還沒有讀過的書。希望你的指點。這裏的服務代碼:

package yada.yada.boom.Setlines; 

import android.app.Notification; 
import android.app.NotificationManager; 
import android.app.PendingIntent; 
import android.app.Service; 
import android.content.Context; 
import android.content.Intent; 
import android.os.Bundle; 
import android.os.IBinder; 
import android.text.ClipboardManager; 
import android.util.Log; 

public class NoteManager extends Service { 

    private NotificationManager mNM = null; 
    private Notification notification = null; 
    private Context context; 
    private final CharSequence contentTitle = "Setlines"; 
    private CharSequence contentText; 
    private Intent notificationIntent; 
    private PendingIntent pendingIntent; 
    private int notificationId = 0; 
    private final String MY_TAG = "SetlinesSvc"; 

    @Override 
    public void onCreate() { 
     super.onCreate(); 
    } 

    @Override 
    public int onStartCommand(Intent intent, int flags, int startId) { 
     long setNbr = 0L; 
     String setMsg = null; 

     super.onStartCommand(intent, flags, startId); 
     context = getApplicationContext(); 
     if (intent != null) { 
      Bundle extras = intent.getExtras(); 
      if (extras != null) { 
       setNbr = extras.getLong(getString(R.string.intent_key_setnbr)); 
       setMsg = extras 
         .getString(getString(R.string.intent_key_setmsg)); 
      } 
     } 
     if ((setNbr == 0L) || (setMsg == null)) { 
      Log.d(MY_TAG, "Setting default message."); 
      setNbr = 0L; 
      setMsg = "Click to view setMsg."; 
     } else { 
      Log.d(MY_TAG, "Got set number (" + setNbr + ") and string (" 
        + setMsg.substring(0, 10) + "...) from intent."); 
     } 
     if (notification == null) { 
      createNotification(setNbr, setMsg); 
     } else { 
      updateNotificationText(setNbr, setMsg); 
     } 
     return START_STICKY; 
    } 

    @Override 
    public void onDestroy() { 
     // Log.d(MY_TAG, "onDestroy() called"); 
     mNM.cancel(notificationId); 
     super.onDestroy(); 
    } 

    @Override 
    public IBinder onBind(Intent arg0) { 
     // TODO Auto-generated method stub 
     return null; 
    } 

    // Create a status bar notification 
    void createNotification(long setNbr, String setMsg) { 
     CharSequence tickerText = null; 
     int icon = 0; 

     // Log.d(MY_TAG, "createNotification called"); 
     mNM = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); 

     icon = R.drawable.ic_notification; 
     tickerText = "Setlines"; 

     // Instantiate the Notification 

     long when = System.currentTimeMillis(); 

     notification = new Notification(icon, tickerText, when); 

     context = getApplicationContext(); 
     contentText = setMsg; 
     notificationIntent = new Intent(this, SetServiceMenu.class); 
     Bundle bundle = new Bundle(); 
     bundle.putLong(getString(R.string.intent_key_setnbr), setNbr); 
     if (setNbr != 0L) { 
      bundle.putString(getString(R.string.intent_key_setmsg), setMsg); 
      Log.d(MY_TAG, "Added extras: SetNbr(" + setNbr + ") SetMsg(" 
        + setMsg.substring(0, 10) + "...)"); 
      notificationIntent.putExtras(bundle); 
     } 
     pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 
       PendingIntent.FLAG_ONE_SHOT); 
     notification.setLatestEventInfo(context, contentTitle, contentText, 
       pendingIntent); 
     notificationId += 1; // Bump the notification ID number 
     // Pass the Notification to the NotificationManager: 
     Log.d(MY_TAG, "createNotification() ... passing notification"); 
     mNM.notify(notificationId, notification); 
     startForeground(notificationId, notification); 
    } 

    void updateNotificationText(long setNbr, String setMsg) { 
     contentText = setMsg; 
     notificationIntent = new Intent(this, SetServiceMenu.class); 
     Bundle bundle = new Bundle(); 
     bundle.putLong(getString(R.string.intent_key_setnbr), setNbr); 
     bundle.putString(getString(R.string.intent_key_setmsg), setMsg); 
     // notificationIntent.putExtras(bundle); 
     notificationIntent.replaceExtras(bundle); 
      Log.d(MY_TAG, "Replaced extras: SetNbr(" + setNbr + ") SetMsg(" 
        + setMsg.substring(0, 10) + "...)"); 
     pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 
       PendingIntent.FLAG_ONE_SHOT); 
     notification.setLatestEventInfo(context, contentTitle, contentText, 
       pendingIntent); 

     mNM.notify(notificationId, notification); 
    } 

} 

...這裏是從活動中的onCreate被稱爲:

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    context = this.getApplicationContext(); 
    Bundle extras = getIntent().getExtras(); 
    String setMsg = ""; 

    dbAdapter = new SetDbAdapter(context); 

    dbAdapter.openReadable(); 
    if (savedInstanceState != null) { 
     setNbr = savedInstanceState.getLong("setNbr"); 
     // Log.d(MY_TAG, "Retrieved set# (" + setNbr + ") from intent."); 
     setMsg = savedInstanceState.getString("setMsg"); 
     // Log.d(MY_TAG, "Retrieved text (" + setMsg.substring(0, 10) 
     // + "...) from intent."); 
     setMsg = dbAdapter.getSetById(setNbr); 
    } else if (extras != null) { 
     setNbr = extras.getLong(getString(R.string.intent_key_setnbr)); 
     // Log.d(MY_TAG, "Retrieved set# (" + setNbr + ") from extras."); 
     setMsg = extras.getString(getString(R.string.intent_key_setline)); 

     if ((setMsg == null) && (setNbr != 0)) { 
      setMsg = dbAdapter.getSetById(setNbr); 
     } 
    } 
    if ((setNbr == 0) || (setMsg == null)) { 
     setNbr = nextMessageNbr(); 
     setMsg = messageText(setNbr); 
    } 
    dbAdapter.close(); 
    svcTagNbr = setNbr; 
    svcTagline = setMsg; 
    d = new myDialog(this); 
    d.show(); 
    notifyService(false); 
} 

最後,這裏是notifyService()

private void notifyService(boolean getNew) { 

    // Here we get a new setMsg, and notify the server to create 
    // notification with it. 
    long mySetNbr = svcSetNbr; 
    String mySetMsg = svcSetMsg; 

    if (getNew) { 
    mySetNbr = nextMessageNbr(); 
    mySetline = messageText(mySetNbr); 
    } 

    Intent srvIntent = new Intent(context, SetManager.class); 
    Bundle bundle = new Bundle(); 
    bundle.putLong(getString(R.string.intent_key_setnbr), mySetNbr); 
    bundle.putString(getString(R.string.intent_key_setmsg), mySetMsg); 
    srvIntent.putExtras(bundle); 
    startService(srvIntent); 
} 

這是所有由於我似乎無法找到調試服務的方法這一事實而複雜化。調試服務的任何指針也將非常感謝!

回答

6

找到了!問題在於失蹤的標誌。顯然,即使我們使用updateExtras(),除非在getActivity()方法上使用特殊標誌(FLAG_UPDATE_CURRENT),否則Android不會引起注意。

從文檔在http://developer.android.com/reference/android/app/PendingIntent.html

...如果所描述的PendingIntent已經存在,則保持它但什麼是在這個新的意圖替換其額外數據。如果你正在創建只有額外變化的意圖,可以使用它,並且不關心任何接收你以前的PendingIntent的實體將能夠使用你的新的額外功能啓動它,即使它們沒有被明確地賦予它。

因此,新的代碼如下所示:

void updateNotificationText(long setNbr, String setMsg) { 
    contentText = setMsg; 
    Bundle bundle = new Bundle(); 
    bundle.putLong(getString(R.string.intent_key_setnbr), setNbr); 
    bundle.putString(getString(R.string.intent_key_setmsg), setMsg); 
    notificationIntent.replaceExtras(bundle); 
    pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 
      PendingIntent.FLAG_ONE_SHOT 
     + PendingIntent.FLAG_UPDATE_CURRENT); 
    notification.setLatestEventInfo(context, contentTitle, contentText, 
      pendingIntent); 
    mNM.notify(notificationId, notification); 
} 
+0

感謝@Dennis,這很好地整理我的問題 - 你可以標記您自己的答案所接受? – danmux