根据我对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作为Intent传递给BackgroundService类,但是没有内置的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 :(得分:1)
您没有绑定到您尝试启动该服务的服务(使用bindService完成)。如果你想绑定你应该使用bindService并从javadoc和你指定的链接读取该行为。
就独立Handler
不起作用而言:这取决于BackgroundService
的实施。
答案 1 :(得分:0)
我可以成功将活动绑定到我的服务,如下所示:
bindService(new Intent(Binding.this, LocalService.class), mConnection, Context.BIND_AUTO_CREATE);