Notice the use of the {@link NotificationManager} when interesting things @@ -49,6 +41,7 @@ import com.example.android.apis.R; * interact with the user, rather than doing something more disruptive such as * calling startActivity(). */ +//BEGIN_INCLUDE(service) public class LocalService extends Service { private NotificationManager mNM; @@ -110,7 +103,7 @@ public class LocalService extends Service { // The PendingIntent to launch our activity if the user selects this notification PendingIntent contentIntent = PendingIntent.getActivity(this, 0, - new Intent(this, Controller.class), 0); + new Intent(this, LocalServiceActivities.Controller.class), 0); // Set the info for the views that show in the notification panel. notification.setLatestEventInfo(this, getText(R.string.local_service_label), @@ -120,127 +113,5 @@ public class LocalService extends Service { // We use a layout id because it is a unique number. We use it later to cancel. mNM.notify(R.string.local_service_started, notification); } - - // ---------------------------------------------------------------------- - - /** - *
Example of explicitly starting and stopping the local service. - * This demonstrates the implementation of a service that runs in the same - * process as the rest of the application, which is explicitly started and stopped - * as desired.
- * - *Note that this is implemented as an inner class only keep the sample - * all together; typically this code would appear in some separate class. - */ - public static class Controller extends Activity { - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - setContentView(R.layout.local_service_controller); - - // Watch for button clicks. - Button button = (Button)findViewById(R.id.start); - button.setOnClickListener(mStartListener); - button = (Button)findViewById(R.id.stop); - button.setOnClickListener(mStopListener); - } - - private OnClickListener mStartListener = new OnClickListener() { - public void onClick(View v) { - // Make sure the service is started. It will continue running - // until someone calls stopService(). The Intent we use to find - // the service explicitly specifies our service component, because - // we want it running in our own process and don't want other - // applications to replace it. - startService(new Intent(Controller.this, - LocalService.class)); - } - }; - - private OnClickListener mStopListener = new OnClickListener() { - public void onClick(View v) { - // Cancel a previous call to startService(). Note that the - // service will not actually stop at this point if there are - // still bound clients. - stopService(new Intent(Controller.this, - LocalService.class)); - } - }; - } - - // ---------------------------------------------------------------------- - - /** - * Example of binding and unbinding to the local service. - * This demonstrates the implementation of a service which the client will - * bind to, receiving an object through which it can communicate with the service.
- * - *Note that this is implemented as an inner class only keep the sample - * all together; typically this code would appear in some separate class. - */ - public static class Binding extends Activity { - private boolean mIsBound; - private LocalService mBoundService; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - setContentView(R.layout.local_service_binding); - - // Watch for button clicks. - Button button = (Button)findViewById(R.id.bind); - button.setOnClickListener(mBindListener); - button = (Button)findViewById(R.id.unbind); - button.setOnClickListener(mUnbindListener); - } - - private ServiceConnection mConnection = new ServiceConnection() { - public void onServiceConnected(ComponentName className, IBinder service) { - // This is called when the connection with the service has been - // established, giving us the service object we can use to - // interact with the service. Because we have bound to a explicit - // service that we know is running in our own process, we can - // cast its IBinder to a concrete class and directly access it. - mBoundService = ((LocalService.LocalBinder)service).getService(); - - // Tell the user about this for our demo. - Toast.makeText(Binding.this, R.string.local_service_connected, - Toast.LENGTH_SHORT).show(); - } - - public void onServiceDisconnected(ComponentName className) { - // This is called when the connection with the service has been - // unexpectedly disconnected -- that is, its process crashed. - // Because it is running in our same process, we should never - // see this happen. - mBoundService = null; - Toast.makeText(Binding.this, R.string.local_service_disconnected, - Toast.LENGTH_SHORT).show(); - } - }; - - private OnClickListener mBindListener = new OnClickListener() { - public void onClick(View v) { - // Establish a connection with the service. We use an explicit - // class name because we want a specific service implementation that - // we know will be running in our own process (and thus won't be - // supporting component replacement by other applications). - bindService(new Intent(Binding.this, - LocalService.class), mConnection, Context.BIND_AUTO_CREATE); - mIsBound = true; - } - }; - - private OnClickListener mUnbindListener = new OnClickListener() { - public void onClick(View v) { - if (mIsBound) { - // Detach our existing connection. - unbindService(mConnection); - mIsBound = false; - } - } - }; - } } +//END_INCLUDE(service) diff --git a/samples/ApiDemos/src/com/example/android/apis/app/LocalServiceActivities.java b/samples/ApiDemos/src/com/example/android/apis/app/LocalServiceActivities.java new file mode 100644 index 000000000..a6c3fd822 --- /dev/null +++ b/samples/ApiDemos/src/com/example/android/apis/app/LocalServiceActivities.java @@ -0,0 +1,171 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.android.apis.app; + +import com.example.android.apis.R; + +import android.app.Activity; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.Bundle; +import android.os.IBinder; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.Button; +import android.widget.Toast; + +public class LocalServiceActivities { + /** + *
Example of explicitly starting and stopping the local service. + * This demonstrates the implementation of a service that runs in the same + * process as the rest of the application, which is explicitly started and stopped + * as desired.
+ * + *Note that this is implemented as an inner class only keep the sample + * all together; typically this code would appear in some separate class. + */ + public static class Controller extends Activity { + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setContentView(R.layout.local_service_controller); + + // Watch for button clicks. + Button button = (Button)findViewById(R.id.start); + button.setOnClickListener(mStartListener); + button = (Button)findViewById(R.id.stop); + button.setOnClickListener(mStopListener); + } + + private OnClickListener mStartListener = new OnClickListener() { + public void onClick(View v) { + // Make sure the service is started. It will continue running + // until someone calls stopService(). The Intent we use to find + // the service explicitly specifies our service component, because + // we want it running in our own process and don't want other + // applications to replace it. + startService(new Intent(Controller.this, + LocalService.class)); + } + }; + + private OnClickListener mStopListener = new OnClickListener() { + public void onClick(View v) { + // Cancel a previous call to startService(). Note that the + // service will not actually stop at this point if there are + // still bound clients. + stopService(new Intent(Controller.this, + LocalService.class)); + } + }; + } + + // ---------------------------------------------------------------------- + + /** + * Example of binding and unbinding to the local service. + * This demonstrates the implementation of a service which the client will + * bind to, receiving an object through which it can communicate with the service.
+ * + *Note that this is implemented as an inner class only keep the sample + * all together; typically this code would appear in some separate class. + */ + public static class Binding extends Activity { + private boolean mIsBound; + +// BEGIN_INCLUDE(bind) + private LocalService mBoundService; + + private ServiceConnection mConnection = new ServiceConnection() { + public void onServiceConnected(ComponentName className, IBinder service) { + // This is called when the connection with the service has been + // established, giving us the service object we can use to + // interact with the service. Because we have bound to a explicit + // service that we know is running in our own process, we can + // cast its IBinder to a concrete class and directly access it. + mBoundService = ((LocalService.LocalBinder)service).getService(); + + // Tell the user about this for our demo. + Toast.makeText(Binding.this, R.string.local_service_connected, + Toast.LENGTH_SHORT).show(); + } + + public void onServiceDisconnected(ComponentName className) { + // This is called when the connection with the service has been + // unexpectedly disconnected -- that is, its process crashed. + // Because it is running in our same process, we should never + // see this happen. + mBoundService = null; + Toast.makeText(Binding.this, R.string.local_service_disconnected, + Toast.LENGTH_SHORT).show(); + } + }; + + void doBindService() { + // Establish a connection with the service. We use an explicit + // class name because we want a specific service implementation that + // we know will be running in our own process (and thus won't be + // supporting component replacement by other applications). + bindService(new Intent(Binding.this, + LocalService.class), mConnection, Context.BIND_AUTO_CREATE); + mIsBound = true; + } + + void doUnbindService() { + if (mIsBound) { + // Detach our existing connection. + unbindService(mConnection); + mIsBound = false; + } + } + + @Override + protected void onDestroy() { + super.onDestroy(); + doUnbindService(); + } +// END_INCLUDE(bind) + + private OnClickListener mBindListener = new OnClickListener() { + public void onClick(View v) { + doBindService(); + } + }; + + private OnClickListener mUnbindListener = new OnClickListener() { + public void onClick(View v) { + doUnbindService(); + } + }; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setContentView(R.layout.local_service_binding); + + // Watch for button clicks. + Button button = (Button)findViewById(R.id.bind); + button.setOnClickListener(mBindListener); + button = (Button)findViewById(R.id.unbind); + button.setOnClickListener(mUnbindListener); + } + } +} diff --git a/samples/ApiDemos/src/com/example/android/apis/app/MessengerService.java b/samples/ApiDemos/src/com/example/android/apis/app/MessengerService.java new file mode 100644 index 000000000..a21763e3e --- /dev/null +++ b/samples/ApiDemos/src/com/example/android/apis/app/MessengerService.java @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.android.apis.app; + +import android.app.Notification; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.app.Service; +import android.content.Intent; +import android.os.Binder; +import android.os.Handler; +import android.os.IBinder; +import android.os.Message; +import android.os.Messenger; +import android.os.RemoteException; +import android.util.Log; +import android.widget.Toast; + +import java.util.ArrayList; + +// Need the following import to get access to the app resources, since this +// class is in a sub-package. +import com.example.android.apis.R; +import com.example.android.apis.app.RemoteService.Controller; + +/** + * This is an example of implementing an application service that uses the + * {@link Messenger} class for communicating with clients. This allows for + * remote interaction with a service, without needing to define an AIDL + * interface. + * + *
Notice the use of the {@link NotificationManager} when interesting things
+ * happen in the service. This is generally how background services should
+ * interact with the user, rather than doing something more disruptive such as
+ * calling startActivity().
+ */
+//BEGIN_INCLUDE(service)
+public class MessengerService extends Service {
+ /** For showing and hiding our notification. */
+ NotificationManager mNM;
+ /** Keeps track of all current registered clients. */
+ ArrayList
Note that this is implemented as an inner class only keep the sample + * all together; typically this code would appear in some separate class. + */ + public static class Binding extends Activity { +// BEGIN_INCLUDE(bind) + /** Messenger for communicating with service. */ + Messenger mService = null; + /** Flag indicating whether we have called bind on the service. */ + boolean mIsBound; + /** Some text view we are using to show state information. */ + TextView mCallbackText; + + /** + * Handler of incoming messages from service. + */ + class IncomingHandler extends Handler { + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MessengerService.MSG_SET_VALUE: + mCallbackText.setText("Received from service: " + msg.arg1); + break; + default: + super.handleMessage(msg); + } + } + } + + /** + * Target we publish for clients to send messages to IncomingHandler. + */ + final Messenger mMessenger = new Messenger(new IncomingHandler()); + + /** + * Class for interacting with the main interface of the service. + */ + private ServiceConnection mConnection = new ServiceConnection() { + public void onServiceConnected(ComponentName className, + IBinder service) { + // This is called when the connection with the service has been + // established, giving us the service object we can use to + // interact with the service. We are communicating with our + // service through an IDL interface, so get a client-side + // representation of that from the raw service object. + mService = new Messenger(service); + mCallbackText.setText("Attached."); + + // We want to monitor the service for as long as we are + // connected to it. + try { + Message msg = Message.obtain(null, + MessengerService.MSG_REGISTER_CLIENT); + msg.replyTo = mMessenger; + mService.send(msg); + + // Give it some value as an example. + msg = Message.obtain(null, + MessengerService.MSG_SET_VALUE, this.hashCode(), 0); + mService.send(msg); + } catch (RemoteException e) { + // In this case the service has crashed before we could even + // do anything with it; we can count on soon being + // disconnected (and then reconnected if it can be restarted) + // so there is no need to do anything here. + } + + // As part of the sample, tell the user what happened. + Toast.makeText(Binding.this, R.string.remote_service_connected, + Toast.LENGTH_SHORT).show(); + } + + public void onServiceDisconnected(ComponentName className) { + // This is called when the connection with the service has been + // unexpectedly disconnected -- that is, its process crashed. + mService = null; + mCallbackText.setText("Disconnected."); + + // As part of the sample, tell the user what happened. + Toast.makeText(Binding.this, R.string.remote_service_disconnected, + Toast.LENGTH_SHORT).show(); + } + }; + + void doBindService() { + // Establish a connection with the service. We use an explicit + // class name because there is no reason to be able to let other + // applications replace our component. + bindService(new Intent(Binding.this, + MessengerService.class), mConnection, Context.BIND_AUTO_CREATE); + mIsBound = true; + mCallbackText.setText("Binding."); + } + + void doUnbindService() { + if (mIsBound) { + // If we have received the service, and hence registered with + // it, then now is the time to unregister. + if (mService != null) { + try { + Message msg = Message.obtain(null, + MessengerService.MSG_UNREGISTER_CLIENT); + msg.replyTo = mMessenger; + mService.send(msg); + } catch (RemoteException e) { + // There is nothing special we need to do if the service + // has crashed. + } + } + + // Detach our existing connection. + unbindService(mConnection); + mIsBound = false; + mCallbackText.setText("Unbinding."); + } + } + // END_INCLUDE(bind) + + /** + * Standard initialization of this activity. Set up the UI, then wait + * for the user to poke it before doing anything. + */ + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setContentView(R.layout.messenger_service_binding); + + // Watch for button clicks. + Button button = (Button)findViewById(R.id.bind); + button.setOnClickListener(mBindListener); + button = (Button)findViewById(R.id.unbind); + button.setOnClickListener(mUnbindListener); + + mCallbackText = (TextView)findViewById(R.id.callback); + mCallbackText.setText("Not attached."); + } + + private OnClickListener mBindListener = new OnClickListener() { + public void onClick(View v) { + doBindService(); + } + }; + + private OnClickListener mUnbindListener = new OnClickListener() { + public void onClick(View v) { + doUnbindService(); + } + }; + } +}