I created a simple Android application to check how to use a handler or handlers to transfer data from a help desk / thread to a different activity than MainActivity, which created a background service. I have a Service, thread, and handler working in MainActivity. The last step is to get a handler for transferring data to another activity than MainActivity. I can get the Service to pass messages to the MainActivity handler, but I donโt know how to get it to pass data to another activity.
Why does anyone want to do this? I thought it was compared to a simple MP3 player, but what it actually compares is a good FM radio. MainActivity uses a background service that allows me to select an FM station. When I run the Play action, it needs to bind to the same background service so that I can continue listening while it (the pretty part) displays a graphic equalizer or an animation of the audio. Basically, I donโt know how to bind to a background service from several operations.
My code was originally based on the Service page 304 in Pro Android 2 and was extremely helpful . CommonsWare sample application .
Please take a look at my current code. It consists of three carefully commented files that describe what I'm trying to do, and the difficulties that I have in transferring data to another activity in addition to MainActivity:
/************************************************************************************************** * 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); Log.d(TAG, "starting service"); /* * 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. Intent backgroundService = new Intent(MainActivity.this, com.marie.mainactivity.BackgroundService.class); backgroundService.putExtra(BackgroundService.EXTRA_MESSENGER, new Messenger(handler)); startService(backgroundService); // Start the RcvMessages activity to receive messages from the handler. But how??? Intent messages = new Intent(MainActivity.this, com.marie.mainactivity.RcvMessages.class); 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 handler = new Handler() { @Override public void handleMessage(Message msg) { // simple handler test (does not send messages to RcvMessages activity String obj = (String) msg.obj; Log.i("handleMessge", "obj: " + obj); } }; } /************************************************************************************************** * 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; /* * 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 = "com.marie.mainactivity.EXTRA_MESSENGER"; private Messenger messenger; @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 class try { Message msg1 = Message.obtain(); msg1.obj = "Hello 1"; messenger.send(msg1); } catch (RemoteException e) { e.printStackTrace(); } // 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(); } /* * onStart is where we get our reference the Messenger that allows * us to send messages to the handler defined in the MainActivity class. */ @Override public void onStart(Intent intent, int startId) { super.onStart(intent, startId); Bundle extras = intent.getExtras(); messenger = (Messenger)extras.get(EXTRA_MESSENGER); } @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.os.Bundle; import android.text.InputType; 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 { 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"); } }
Any help using the background service, thread, and handler (s) to transfer data to other actions in addition to the MainActivity that created the backgraound service is welcome.