2011-06-18 62 views
0

從我已閱讀的關於Services我應該可以有多個活動綁定到同一個服務,但它不起作用。什麼是值得我的BackgroundService延伸服務。開始/綁定到服務的多個活動

從我的MainActivity我啓動服務如下:

Intent backgroundService = new Intent(MainActivity.this, BackgroundService.class); 
backgroundService.putExtra(BackgroundService.EXTRA_MESSENGER_MAINACTIVITY, new Messenger(mainHandler)); 
startService(backgroundService); 

然後從另一個活動我嘗試綁定此相同的服務如下:

Intent backgroundService = new Intent(RcvMessages.this, BackgroundService.class); 
backgroundService.putExtra(BackgroundService.EXTRA_MESSENGER_RCVMESSAGES, new Messenger(rcvHandler)); 
startService(backgroundService); 

我的理解是,每一個綁定的如上所述,服務將擁有自己的處理程序。但它不起作用。只有第一個處理程序工作。我究竟做錯了什麼?

@Femi說:「您傳遞給Messenger作爲額外的BackgroundService類的Intent,但是沒有內置的Android代碼來理解如何處理該Messenger:必須由BackgroundService實現提供。BackgroundService的代碼是什麼,它對傳遞的Messenger實例做了什麼?「 @Femi看看我的BackgroundSerive,特別是onStartCommand():

/************************************************************************************************** 
* File: BackgroundService.java 
* Application: BackgroundService 
* Description: This file contains the background Service that is launched by the MainActivity's 
*  bind button. 
**************************************************************************************************/ 

package com.marie.mainactivity; 

import android.app.Notification; 
import android.app.NotificationManager; 
import android.app.PendingIntent; 
import android.app.Service; 
import android.content.Intent; 
import android.os.Bundle; 
import android.os.IBinder; 
import android.os.Message; 
import android.os.Messenger; 
import android.os.RemoteException; 
import android.util.Log; 

/* 
* Class: BackgroundService 
* Purpose: Using the onStart() method the BackgroundService gets the reference to the 
*  Messenger instance that was passed to BackgroundService. The messenger is then 
*  used by the ServiceWorker() thread to send messages to the handler that is defined 
*  in the MainActivity class. 
*/ 
public class BackgroundService extends Service { 
    private NotificationManager notificationMgr; 

    public static final String EXTRA_MESSENGER_MAINACTIVITY = "com.marie.mainactivity.EXTRA_MESSENGER_MAINACTIVITY"; 
    private Messenger messenger_mainactivity; 

    public static final String EXTRA_MESSENGER_RCVMESSAGES = "com.marie.mainactivity.EXTRA_MESSENGER_RCVMESSAGES"; 
    private Messenger messenger_rcvmessages; 

    public static final String EXTRA_SONG = "com.marie.mainactivity.EXTRA_SONG"; 
    int song = 0; 

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

     notificationMgr = (NotificationManager)getSystemService(NOTIFICATION_SERVICE); 

     displayNotificationMessage("starting Background Service"); 

     Thread thr = new Thread(null, new ServiceWorker(), "BackgroundService"); 
     thr.start(); 
    } 

    /* 
    * This is the ServiceWorker thread that passes messages to the handler defined in 
    * the MainActivity class. 
    * NOTE: Instead of passing messages to a handler in MainActivity I would like 
    * it to pass messages to a handler defined in the RcvMessages activity. 
    */ 
    class ServiceWorker implements Runnable 
    { 
     public void run() { 
      // do background processing here... something simple 

      // send a message to the handler defined in the MainActivity activity 
      if (messenger_mainactivity != null) 
      { 
       try { 
        Message msg1 = Message.obtain(); 
        msg1.obj = "SongData"; 
        msg1.arg1 = 1000; 
        messenger_mainactivity.send(msg1); 
       } catch (RemoteException e) { 
        e.printStackTrace(); 
       } catch (NullPointerException e) { 
        e.printStackTrace(); 
       } 
      } else { 
       Log.e("messenger_mainactivity", "null"); 
      } 

      // send a message to the handler defined in the RcvMessages activity 
      if (messenger_rcvmessages != null) 
      { 
       try { 
        Message msg1 = Message.obtain(); 
        msg1.obj = "Song"; 
        msg1.arg1 = song; 
        messenger_rcvmessages.send(msg1); 
       } catch (RemoteException e) { 
        e.printStackTrace(); 
       } catch (NullPointerException e) { 
        e.printStackTrace(); 
       } 
      } else { 
       Log.e("messenger_rcvmessages", "null"); 
      } 

      // stop the service when done... 
      // BackgroundService.this.stopSelf(); 
      // Or use the unbindBtn in the MainActivity class. 
     } 
    } 

    @Override 
    public void onDestroy() 
    { 
     displayNotificationMessage("stopping Background Service"); 
     super.onDestroy(); 
    } 

    /* 
    @Override 
    public void onStart(Intent intent, int startId) { 
     super.onStart(intent, startId); 
    } 
    */ 

    @Override 
    public int onStartCommand(Intent intent, int flags, int startId) { 
     super.onStartCommand(intent, flags, startId); 

     Bundle extras = intent.getExtras(); 
     Messenger messenger; 

     messenger = (Messenger)extras.get(EXTRA_MESSENGER_MAINACTIVITY); 
     if (messenger != null) { 
      messenger_mainactivity = messenger; 
     } 

     messenger = (Messenger)extras.get(EXTRA_MESSENGER_RCVMESSAGES); 
     if (messenger != null) { 
      messenger_rcvmessages = messenger; 
      song = extras.getInt(EXTRA_SONG); 
     } 

     return START_NOT_STICKY; 
    } 

    @Override 
    public IBinder onBind(Intent intent) { 
     return null; 
    } 

    private void displayNotificationMessage(String message) 
    { 
     Notification notification = new Notification(R.drawable.note, message, System.currentTimeMillis()); 

     PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, MainActivity.class), 0); 

     notification.setLatestEventInfo(this, "Background Service", message, contentIntent); 

     notificationMgr.notify(R.id.app_notification_id, notification); 
    } 
} 

這裏是整個代碼:

/************************************************************************************************** 
* File: MainActivity.java 
* Application: BackgroundService 
* Description: This file contains the main activity that is run when the BackgroundService 
*  application is launched. 
**************************************************************************************************/ 

package com.marie.mainactivity; 

import com.marie.mainactivity.BackgroundService; 
import android.app.Activity; 
import android.content.Intent; 
import android.os.Bundle; 
import android.os.Handler; 
import android.os.Message; 
import android.os.Messenger; 
import android.util.Log; 
import android.view.View; 
import android.view.View.OnClickListener; 
import android.widget.Button; 

/* 
* Class: MainActivity 
* Purpose: Using a button, the MainActivity class starts the backgroundService and 
*  the RcvMessages activity. Using another button MainActivity stops the backgroundService. 
*  NOTE: RcvMessages is only a stub that does nothing but display a simple message. 
* Handler: MainActivity defines and provides a reference to "handler" for the backgroundService. 
*/ 
public class MainActivity extends Activity { 
    private static final String TAG = "MainActivity"; 

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

     /* 
     * The bind button: bindBtn 
     * Clicking this button starts the background Service and launches the 
     * RcvMessages activity. NOTE: RcvMessages is only a stub so far. 
     */ 
     Button bindBtn = (Button)findViewById(R.id.bindBtn); 
     bindBtn.setOnClickListener(new OnClickListener() { 

      @Override 
      public void onClick(View arg0) { 
       // Start the background Service for sending canned messages to the handler as a test. 
       Log.d(TAG, "starting service"); 
       Intent backgroundService = new Intent(MainActivity.this, BackgroundService.class); 
       backgroundService.putExtra(BackgroundService.EXTRA_MESSENGER_MAINACTIVITY, new Messenger(mainHandler)); 
       startService(backgroundService); 

       // Start the RcvMessages activity to receive messages from the handler. But how??? 
       Intent messages = new Intent(MainActivity.this, RcvMessages.class); 
       messages.putExtra(RcvMessages.EXTRA_SONG, 10); 
       startActivity(messages); 
      } 
     }); 

     /* 
     * The unbind button: unbindBtn 
     * Clicking this button stops the background Service. 
     */ 
     Button unbindBtn = (Button)findViewById(R.id.unbindBtn); 
     unbindBtn.setOnClickListener(new OnClickListener() { 

      @Override 
      public void onClick(View arg0) { 

       // Stop the background Service 
       Intent backgroundService = new Intent(MainActivity.this, BackgroundService.class); 
       stopService(backgroundService); 
      } 
     }); 
    } 

    /* 
    * This is the handler to be passed to the background Service via a Messenger. 
    * NOTE: I want it to send messages to my RcvMessages activity. 
    */ 
    private Handler mainHandler = new Handler() { 
     @Override 
     public void handleMessage(Message msg) { 
      // simple handler test (does not send messages to RcvMessages activity 
      String obj = (String) msg.obj; 
      int arg1 = msg.arg1; 
      Log.i("handleMessge_mainactivity", "obj: " + obj + " " + "arg1: " + arg1); 
     } 
    }; 
} 


/************************************************************************************************** 
* File: BackgroundService.java 
* Application: BackgroundService 
* Description: This file contains the background Service that is launched by the MainActivity's 
*  bind button. 
**************************************************************************************************/ 

package com.marie.mainactivity; 

import android.app.Notification; 
import android.app.NotificationManager; 
import android.app.PendingIntent; 
import android.app.Service; 
import android.content.Intent; 
import android.os.Bundle; 
import android.os.IBinder; 
import android.os.Message; 
import android.os.Messenger; 
import android.os.RemoteException; 
import android.util.Log; 

/* 
* Class: BackgroundService 
* Purpose: Using the onStart() method the BackgroundService gets the reference to the 
*  Messenger instance that was passed to BackgroundService. The messenger is then 
*  used by the ServiceWorker() thread to send messages to the handler that is defined 
*  in the MainActivity class. 
*/ 
public class BackgroundService extends Service { 
    private NotificationManager notificationMgr; 

    public static final String EXTRA_MESSENGER_MAINACTIVITY = "com.marie.mainactivity.EXTRA_MESSENGER_MAINACTIVITY"; 
    private Messenger messenger_mainactivity; 

    public static final String EXTRA_MESSENGER_RCVMESSAGES = "com.marie.mainactivity.EXTRA_MESSENGER_RCVMESSAGES"; 
    private Messenger messenger_rcvmessages; 

    public static final String EXTRA_SONG = "com.marie.mainactivity.EXTRA_SONG"; 
    int song = 0; 

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

     notificationMgr = (NotificationManager)getSystemService(NOTIFICATION_SERVICE); 

     displayNotificationMessage("starting Background Service"); 

     Thread thr = new Thread(null, new ServiceWorker(), "BackgroundService"); 
     thr.start(); 
    } 

    /* 
    * This is the ServiceWorker thread that passes messages to the handler defined in 
    * the MainActivity class. 
    * NOTE: Instead of passing messages to a handler in MainActivity I would like 
    * it to pass messages to a handler defined in the RcvMessages activity. 
    */ 
    class ServiceWorker implements Runnable 
    { 
     public void run() { 
      // do background processing here... something simple 

      // send a message to the handler defined in the MainActivity activity 
      if (messenger_mainactivity != null) 
      { 
       try { 
        Message msg1 = Message.obtain(); 
        msg1.obj = "SongData"; 
        msg1.arg1 = 1000; 
        messenger_mainactivity.send(msg1); 
       } catch (RemoteException e) { 
        e.printStackTrace(); 
       } catch (NullPointerException e) { 
        e.printStackTrace(); 
       } 
      } else { 
       Log.e("messenger_mainactivity", "null"); 
      } 

      // send a message to the handler defined in the RcvMessages activity 
      if (messenger_rcvmessages != null) 
      { 
       try { 
        Message msg1 = Message.obtain(); 
        msg1.obj = "Song"; 
        msg1.arg1 = song; 
        messenger_rcvmessages.send(msg1); 
       } catch (RemoteException e) { 
        e.printStackTrace(); 
       } catch (NullPointerException e) { 
        e.printStackTrace(); 
       } 
      } else { 
       Log.e("messenger_rcvmessages", "null"); 
      } 

      // stop the service when done... 
      // BackgroundService.this.stopSelf(); 
      // Or use the unbindBtn in the MainActivity class. 
     } 
    } 

    @Override 
    public void onDestroy() 
    { 
     displayNotificationMessage("stopping Background Service"); 
     super.onDestroy(); 
    } 

    /* 
    @Override 
    public void onStart(Intent intent, int startId) { 
     super.onStart(intent, startId); 
    } 
    */ 

    @Override 
    public int onStartCommand(Intent intent, int flags, int startId) { 
     super.onStartCommand(intent, flags, startId); 

     Bundle extras = intent.getExtras(); 
     Messenger messenger; 

     messenger = (Messenger)extras.get(EXTRA_MESSENGER_MAINACTIVITY); 
     if (messenger != null) { 
      messenger_mainactivity = messenger; 
     } 

     messenger = (Messenger)extras.get(EXTRA_MESSENGER_RCVMESSAGES); 
     if (messenger != null) { 
      messenger_rcvmessages = messenger; 
      song = extras.getInt(EXTRA_SONG); 
     } 

     return START_NOT_STICKY; 
    } 

    @Override 
    public IBinder onBind(Intent intent) { 
     return null; 
    } 

    private void displayNotificationMessage(String message) 
    { 
     Notification notification = new Notification(R.drawable.note, message, System.currentTimeMillis()); 

     PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, MainActivity.class), 0); 

     notification.setLatestEventInfo(this, "Background Service", message, contentIntent); 

     notificationMgr.notify(R.id.app_notification_id, notification); 
    } 
} 


/************************************************************************************************** 
* File: RcvMessages.java 
* Application: BackgroundService 
* Description: This file contains stub code that displays a test message in an EditText. 
**************************************************************************************************/ 

package com.marie.mainactivity; 

import android.app.Activity; 
import android.content.Intent; 
import android.os.Bundle; 
import android.os.Handler; 
import android.os.Message; 
import android.os.Messenger; 
import android.text.InputType; 
import android.util.Log; 
import android.widget.EditText; 

/* 
* Class: RcvMessages 
* Purpose: RcvMessages is stub code that I want to extend in some way to receive messages from 
*  the background Service. 
*  NOTE: I don't know who to do this. 
*/ 
public class RcvMessages extends Activity { 

    public static final String EXTRA_SONG = "com.marie.mainactivity.EXTRA_SONG"; 
    EditText myText; 

    /** Called when the activity is first created. */ 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.messages); 

     myText = (EditText)findViewById(R.id.my_text); 

     myText.setSingleLine(); 
     myText.setInputType(InputType.TYPE_NULL); 

     // Display a simple test message for now. 
     // myText.setText("RcvMessages here"); 
    } 

    @Override 
    public void onStart(){ 
     super.onStart(); 
     Bundle extras = getIntent().getExtras(); 
     int song = (Integer) extras.get(EXTRA_SONG); 
     //myText.setText("song " + song); 

     // Start the background Service for sending canned messages to the handler as a test. 
     Intent backgroundService = new Intent(RcvMessages.this, BackgroundService.class); 
     backgroundService.putExtra(BackgroundService.EXTRA_MESSENGER_RCVMESSAGES, new Messenger(rcvHandler)); 
     backgroundService.putExtra(BackgroundService.EXTRA_SONG, song); 
     bindService(backgroundService); 
    } 

    private void bindService(Intent backgroundService) { 
     // TODO Auto-generated method stub 

    } 

    @Override 
    public void onStop() { 
     super.onStop(); 
     myText.setText(""); 
    } 

    /* 
    * This is the handler to be passed to the background Service via a Messenger. 
    * NOTE: I want it to send messages to my RcvMessages activity. 
    */ 
    private Handler rcvHandler = new Handler() { 
     @Override 
     public void handleMessage(Message msg) { 
      // simple handler test 
      String song = (String) msg.obj; 
      int songNum = msg.arg1; 
      Log.i("handleMessage_rcvmessages", "songNum: " + songNum); 

      myText.setText(song + " " + songNum); 
     } 
    }; 

} 
+0

會發生什麼事,當你做到這一點? –

+0

@詹姆斯只有一個處理程序工作。 – Marie

回答

1

你是不是綁定到服務(即使用bindService做)你試圖開始服務。如果你想綁定你應該使用bindService並從javadoc和你指定的鏈接上讀取該行爲。

據獨立Handler s不工作:這取決於執行BackgroundService

+0

@Femi請你提供一些細節。你的意思是「這取決於BackgroundService的實現嗎?」 – Marie

+0

您將'Messenger'作爲額外的'Intent'傳遞給BackgroundService類,但是沒有內置的Android代碼可以理解如何處理該Messenger:必須由BackgroundService實現提供。 BackgroundService的代碼是什麼,它對傳遞的Messenger實例有什麼作用? – Femi

+0

@Femi我會相應修改我的問題。 – Marie

0

我可以成功綁定活動,我的服務是這樣的:

bindService(new Intent(Binding.this, LocalService.class), mConnection, Context.BIND_AUTO_CREATE);