Example of explicitly starting and stopping the {@link ForegroundService}. + * + *
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.foreground_service_controller); + + // Watch for button clicks. + Button button = (Button)findViewById(R.id.start_foreground); + button.setOnClickListener(mForegroundListener); + button = (Button)findViewById(R.id.start_background); + button.setOnClickListener(mBackgroundListener); + button = (Button)findViewById(R.id.stop); + button.setOnClickListener(mStopListener); + } + + private OnClickListener mForegroundListener = new OnClickListener() { + public void onClick(View v) { + Intent intent = new Intent(ForegroundService.ACTION_FOREGROUND); + intent.setClass(Controller.this, ForegroundService.class); + startService(intent); + } + }; + + private OnClickListener mBackgroundListener = new OnClickListener() { + public void onClick(View v) { + Intent intent = new Intent(ForegroundService.ACTION_BACKGROUND); + intent.setClass(Controller.this, ForegroundService.class); + startService(intent); + } + }; + + private OnClickListener mStopListener = new OnClickListener() { + public void onClick(View v) { + stopService(new Intent(Controller.this, + ForegroundService.class)); + } + }; + } } diff --git a/samples/ApiDemos/src/com/example/android/apis/app/ForegroundServiceController.java b/samples/ApiDemos/src/com/example/android/apis/app/ForegroundServiceController.java deleted file mode 100644 index a6a6ef366..000000000 --- a/samples/ApiDemos/src/com/example/android/apis/app/ForegroundServiceController.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2009 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; - -// 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 android.app.Activity; -import android.content.ComponentName; -import android.content.Intent; -import android.os.Bundle; -import android.view.View; -import android.view.View.OnClickListener; -import android.widget.Button; - - -/** - *
Example of explicitly starting and stopping the {@link ForegroundService}. - */ -public class ForegroundServiceController extends Activity { - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - setContentView(R.layout.foreground_service_controller); - - // Watch for button clicks. - Button button = (Button)findViewById(R.id.start_foreground); - button.setOnClickListener(mForegroundListener); - button = (Button)findViewById(R.id.start_background); - button.setOnClickListener(mBackgroundListener); - button = (Button)findViewById(R.id.stop); - button.setOnClickListener(mStopListener); - } - - private OnClickListener mForegroundListener = new OnClickListener() { - public void onClick(View v) { - Intent intent = new Intent(ForegroundService.ACTION_FOREGROUND); - intent.setClass(ForegroundServiceController.this, ForegroundService.class); - startService(intent); - } - }; - - private OnClickListener mBackgroundListener = new OnClickListener() { - public void onClick(View v) { - Intent intent = new Intent(ForegroundService.ACTION_BACKGROUND); - intent.setClass(ForegroundServiceController.this, ForegroundService.class); - startService(intent); - } - }; - - private OnClickListener mStopListener = new OnClickListener() { - public void onClick(View v) { - stopService(new Intent(ForegroundServiceController.this, - ForegroundService.class)); - } - }; -} - diff --git a/samples/ApiDemos/src/com/example/android/apis/app/LocalService.java b/samples/ApiDemos/src/com/example/android/apis/app/LocalService.java index 79324a43c..4a4f32428 100644 --- a/samples/ApiDemos/src/com/example/android/apis/app/LocalService.java +++ b/samples/ApiDemos/src/com/example/android/apis/app/LocalService.java @@ -16,15 +16,22 @@ package com.example.android.apis.app; +import android.app.Activity; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; +import android.content.ComponentName; +import android.content.Context; import android.content.Intent; +import android.content.ServiceConnection; import android.os.Binder; +import android.os.Bundle; import android.os.IBinder; -import android.os.Parcel; import android.util.Log; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.Button; import android.widget.Toast; // Need the following import to get access to the app resources, since this @@ -33,8 +40,8 @@ import com.example.android.apis.R; /** * This is an example of implementing an application service that runs locally - * in the same process as the application. The {@link LocalServiceController} - * and {@link LocalServiceBinding} classes show how to interact with the + * in the same process as the application. The {@link Controller} + * and {@link Binding} classes show how to interact with the * service. * *
Notice the use of the {@link NotificationManager} when interesting things @@ -103,7 +110,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, LocalServiceController.class), 0); + new Intent(this, Controller.class), 0); // Set the info for the views that show in the notification panel. notification.setLatestEventInfo(this, getText(R.string.local_service_label), @@ -113,5 +120,127 @@ 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; + } + } + }; + } +} diff --git a/samples/ApiDemos/src/com/example/android/apis/app/LocalServiceBinding.java b/samples/ApiDemos/src/com/example/android/apis/app/LocalServiceBinding.java deleted file mode 100644 index ddcfad5fc..000000000 --- a/samples/ApiDemos/src/com/example/android/apis/app/LocalServiceBinding.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * 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; - - -/** - *
Example of binding and unbinding to the {@link LocalService}. - * This demonstrates the implementation of a service which the client will - * bind to, receiving an object through which it can communicate with the service.
- */ -public class LocalServiceBinding 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(LocalServiceBinding.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(LocalServiceBinding.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(LocalServiceBinding.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; - } - } - }; -} - diff --git a/samples/ApiDemos/src/com/example/android/apis/app/LocalServiceController.java b/samples/ApiDemos/src/com/example/android/apis/app/LocalServiceController.java deleted file mode 100644 index 604124912..000000000 --- a/samples/ApiDemos/src/com/example/android/apis/app/LocalServiceController.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * 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; - -// 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 android.app.Activity; -import android.content.ComponentName; -import android.content.Intent; -import android.os.Bundle; -import android.view.View; -import android.view.View.OnClickListener; -import android.widget.Button; - - -/** - *Example of explicitly starting and stopping the {@link LocalService}. - * 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.
- */ -public class LocalServiceController 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(LocalServiceController.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(LocalServiceController.this, - LocalService.class)); - } - }; -} - diff --git a/samples/ApiDemos/src/com/example/android/apis/app/RemoteService.java b/samples/ApiDemos/src/com/example/android/apis/app/RemoteService.java index c0debbcaf..a62a52490 100644 --- a/samples/ApiDemos/src/com/example/android/apis/app/RemoteService.java +++ b/samples/ApiDemos/src/com/example/android/apis/app/RemoteService.java @@ -16,21 +16,28 @@ package com.example.android.apis.app; +import android.app.Activity; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; +import android.content.ComponentName; +import android.content.Context; import android.content.Intent; +import android.content.ServiceConnection; +import android.os.Bundle; import android.os.RemoteException; import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.os.Process; import android.os.RemoteCallbackList; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.Button; +import android.widget.TextView; import android.widget.Toast; -import java.util.HashMap; - // 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; @@ -39,8 +46,13 @@ import com.example.android.apis.R; * This is an example of implementing an application service that runs in a * different process than the application. Because it can be in another * process, we must use IPC to interact with it. The - * {@link RemoteServiceController} and {@link RemoteServiceBinding} classes + * {@link Controller} and {@link Binding} classes * show how to interact with the service. + * + *Note that most applications do not need to deal with + * the complexity shown here. If your application simply has a service + * running in its own process, the {@link LocalService} sample shows a much + * simpler way to interact with it. */ public class RemoteService extends Service { /** @@ -172,7 +184,7 @@ public class RemoteService extends Service { // The PendingIntent to launch our activity if the user selects this notification PendingIntent contentIntent = PendingIntent.getActivity(this, 0, - new Intent(this, LocalServiceController.class), 0); + new Intent(this, Controller.class), 0); // Set the info for the views that show in the notification panel. notification.setLatestEventInfo(this, getText(R.string.remote_service_label), @@ -182,4 +194,266 @@ public class RemoteService extends Service { // We use a string id because it is a unique number. We use it later to cancel. mNM.notify(R.string.remote_service_started, notification); } + + // ---------------------------------------------------------------------- + + /** + *
Example of explicitly starting and stopping the remove service. + * This demonstrates the implementation of a service that runs in a different + * process than 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.remote_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(). + // We use an action code here, instead of explictly supplying + // the component name, so that other packages can replace + // the service. + startService(new Intent( + "com.example.android.apis.app.REMOTE_SERVICE")); + } + }; + + 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( + "com.example.android.apis.app.REMOTE_SERVICE")); + } + }; + } + + // ---------------------------------------------------------------------- + + /** + * Example of binding and unbinding to the remote service. + * This demonstrates the implementation of a service which the client will + * bind to, interacting with it through an aidl interface.
+ * + *Note that this is implemented as an inner class only keep the sample + * all together; typically this code would appear in some separate class. + */ + // BEGIN_INCLUDE(calling_a_service) + public static class Binding extends Activity { + /** The primary interface we will be calling on the service. */ + IRemoteService mService = null; + /** Another interface we use on the service. */ + ISecondary mSecondaryService = null; + + Button mKillButton; + TextView mCallbackText; + + private boolean mIsBound; + + /** + * 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.remote_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); + mKillButton = (Button)findViewById(R.id.kill); + mKillButton.setOnClickListener(mKillListener); + mKillButton.setEnabled(false); + + mCallbackText = (TextView)findViewById(R.id.callback); + mCallbackText.setText("Not attached."); + } + + /** + * 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 = IRemoteService.Stub.asInterface(service); + mKillButton.setEnabled(true); + mCallbackText.setText("Attached."); + + // We want to monitor the service for as long as we are + // connected to it. + try { + mService.registerCallback(mCallback); + } 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; + mKillButton.setEnabled(false); + 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(); + } + }; + + /** + * Class for interacting with the secondary interface of the service. + */ + private ServiceConnection mSecondaryConnection = new ServiceConnection() { + public void onServiceConnected(ComponentName className, + IBinder service) { + // Connecting to a secondary interface is the same as any + // other interface. + mSecondaryService = ISecondary.Stub.asInterface(service); + mKillButton.setEnabled(true); + } + + public void onServiceDisconnected(ComponentName className) { + mSecondaryService = null; + mKillButton.setEnabled(false); + } + }; + + private OnClickListener mBindListener = new OnClickListener() { + public void onClick(View v) { + // Establish a couple connections with the service, binding + // by interface names. This allows other applications to be + // installed that replace the remote service by implementing + // the same interface. + bindService(new Intent(IRemoteService.class.getName()), + mConnection, Context.BIND_AUTO_CREATE); + bindService(new Intent(ISecondary.class.getName()), + mSecondaryConnection, Context.BIND_AUTO_CREATE); + mIsBound = true; + mCallbackText.setText("Binding."); + } + }; + + private OnClickListener mUnbindListener = new OnClickListener() { + public void onClick(View v) { + if (mIsBound) { + // If we have received the service, and hence registered with + // it, then now is the time to unregister. + if (mService != null) { + try { + mService.unregisterCallback(mCallback); + } catch (RemoteException e) { + // There is nothing special we need to do if the service + // has crashed. + } + } + + // Detach our existing connection. + unbindService(mConnection); + unbindService(mSecondaryConnection); + mKillButton.setEnabled(false); + mIsBound = false; + mCallbackText.setText("Unbinding."); + } + } + }; + + private OnClickListener mKillListener = new OnClickListener() { + public void onClick(View v) { + // To kill the process hosting our service, we need to know its + // PID. Conveniently our service has a call that will return + // to us that information. + if (mSecondaryService != null) { + try { + int pid = mSecondaryService.getPid(); + // Note that, though this API allows us to request to + // kill any process based on its PID, the kernel will + // still impose standard restrictions on which PIDs you + // are actually able to kill. Typically this means only + // the process running your application and any additional + // processes created by that app as shown here; packages + // sharing a common UID will also be able to kill each + // other's processes. + Process.killProcess(pid); + mCallbackText.setText("Killed service process."); + } catch (RemoteException ex) { + // Recover gracefully from the process hosting the + // server dying. + // Just for purposes of the sample, put up a notification. + Toast.makeText(Binding.this, + R.string.remote_call_failed, + Toast.LENGTH_SHORT).show(); + } + } + } + }; + + // ---------------------------------------------------------------------- + // Code showing how to deal with callbacks. + // ---------------------------------------------------------------------- + + /** + * This implementation is used to receive callbacks from the remote + * service. + */ + private IRemoteServiceCallback mCallback = new IRemoteServiceCallback.Stub() { + /** + * This is called by the remote service regularly to tell us about + * new values. Note that IPC calls are dispatched through a thread + * pool running in each process, so the code executing here will + * NOT be running in our main thread like most other things -- so, + * to update the UI, we need to use a Handler to hop over there. + */ + public void valueChanged(int value) { + mHandler.sendMessage(mHandler.obtainMessage(BUMP_MSG, value, 0)); + } + }; + + private static final int BUMP_MSG = 1; + + private Handler mHandler = new Handler() { + @Override public void handleMessage(Message msg) { + switch (msg.what) { + case BUMP_MSG: + mCallbackText.setText("Received from service: " + msg.arg1); + break; + default: + super.handleMessage(msg); + } + } + + }; + } +// END_INCLUDE(calling_a_service) } diff --git a/samples/ApiDemos/src/com/example/android/apis/app/RemoteServiceBinding.java b/samples/ApiDemos/src/com/example/android/apis/app/RemoteServiceBinding.java deleted file mode 100644 index f9ad4e5b0..000000000 --- a/samples/ApiDemos/src/com/example/android/apis/app/RemoteServiceBinding.java +++ /dev/null @@ -1,241 +0,0 @@ -/* - * 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.RemoteException; -import android.os.Handler; -import android.os.IBinder; -import android.os.Message; -import android.os.Process; -import android.view.View; -import android.view.View.OnClickListener; -import android.widget.Button; -import android.widget.TextView; -import android.widget.Toast; - -// BEGIN_INCLUDE(exposing_a_service) -public class RemoteServiceBinding extends Activity { - /** The primary interface we will be calling on the service. */ - IRemoteService mService = null; - /** Another interface we use on the service. */ - ISecondary mSecondaryService = null; - - Button mKillButton; - TextView mCallbackText; - - private boolean mIsBound; - - /** - * 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.remote_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); - mKillButton = (Button)findViewById(R.id.kill); - mKillButton.setOnClickListener(mKillListener); - mKillButton.setEnabled(false); - - mCallbackText = (TextView)findViewById(R.id.callback); - mCallbackText.setText("Not attached."); - } - - /** - * 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 = IRemoteService.Stub.asInterface(service); - mKillButton.setEnabled(true); - mCallbackText.setText("Attached."); - - // We want to monitor the service for as long as we are - // connected to it. - try { - mService.registerCallback(mCallback); - } 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(RemoteServiceBinding.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; - mKillButton.setEnabled(false); - mCallbackText.setText("Disconnected."); - - // As part of the sample, tell the user what happened. - Toast.makeText(RemoteServiceBinding.this, R.string.remote_service_disconnected, - Toast.LENGTH_SHORT).show(); - } - }; - - /** - * Class for interacting with the secondary interface of the service. - */ - private ServiceConnection mSecondaryConnection = new ServiceConnection() { - public void onServiceConnected(ComponentName className, - IBinder service) { - // Connecting to a secondary interface is the same as any - // other interface. - mSecondaryService = ISecondary.Stub.asInterface(service); - mKillButton.setEnabled(true); - } - - public void onServiceDisconnected(ComponentName className) { - mSecondaryService = null; - mKillButton.setEnabled(false); - } - }; - - private OnClickListener mBindListener = new OnClickListener() { - public void onClick(View v) { - // Establish a couple connections with the service, binding - // by interface names. This allows other applications to be - // installed that replace the remote service by implementing - // the same interface. - bindService(new Intent(IRemoteService.class.getName()), - mConnection, Context.BIND_AUTO_CREATE); - bindService(new Intent(ISecondary.class.getName()), - mSecondaryConnection, Context.BIND_AUTO_CREATE); - mIsBound = true; - mCallbackText.setText("Binding."); - } - }; - - private OnClickListener mUnbindListener = new OnClickListener() { - public void onClick(View v) { - if (mIsBound) { - // If we have received the service, and hence registered with - // it, then now is the time to unregister. - if (mService != null) { - try { - mService.unregisterCallback(mCallback); - } catch (RemoteException e) { - // There is nothing special we need to do if the service - // has crashed. - } - } - - // Detach our existing connection. - unbindService(mConnection); - unbindService(mSecondaryConnection); - mKillButton.setEnabled(false); - mIsBound = false; - mCallbackText.setText("Unbinding."); - } - } - }; - - private OnClickListener mKillListener = new OnClickListener() { - public void onClick(View v) { - // To kill the process hosting our service, we need to know its - // PID. Conveniently our service has a call that will return - // to us that information. - if (mSecondaryService != null) { - try { - int pid = mSecondaryService.getPid(); - // Note that, though this API allows us to request to - // kill any process based on its PID, the kernel will - // still impose standard restrictions on which PIDs you - // are actually able to kill. Typically this means only - // the process running your application and any additional - // processes created by that app as shown here; packages - // sharing a common UID will also be able to kill each - // other's processes. - Process.killProcess(pid); - mCallbackText.setText("Killed service process."); - } catch (RemoteException ex) { - // Recover gracefully from the process hosting the - // server dying. - // Just for purposes of the sample, put up a notification. - Toast.makeText(RemoteServiceBinding.this, - R.string.remote_call_failed, - Toast.LENGTH_SHORT).show(); - } - } - } - }; - - // ---------------------------------------------------------------------- - // Code showing how to deal with callbacks. - // ---------------------------------------------------------------------- - - /** - * This implementation is used to receive callbacks from the remote - * service. - */ - private IRemoteServiceCallback mCallback = new IRemoteServiceCallback.Stub() { - /** - * This is called by the remote service regularly to tell us about - * new values. Note that IPC calls are dispatched through a thread - * pool running in each process, so the code executing here will - * NOT be running in our main thread like most other things -- so, - * to update the UI, we need to use a Handler to hop over there. - */ - public void valueChanged(int value) { - mHandler.sendMessage(mHandler.obtainMessage(BUMP_MSG, value, 0)); - } - }; - - private static final int BUMP_MSG = 1; - - private Handler mHandler = new Handler() { - @Override public void handleMessage(Message msg) { - switch (msg.what) { - case BUMP_MSG: - mCallbackText.setText("Received from service: " + msg.arg1); - break; - default: - super.handleMessage(msg); - } - } - - }; -} -// END_INCLUDE(exposing_a_service) - diff --git a/samples/ApiDemos/src/com/example/android/apis/app/RemoteServiceController.java b/samples/ApiDemos/src/com/example/android/apis/app/RemoteServiceController.java deleted file mode 100644 index 681d4111c..000000000 --- a/samples/ApiDemos/src/com/example/android/apis/app/RemoteServiceController.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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; - -// 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 android.app.Activity; -import android.content.Intent; -import android.os.Bundle; -import android.view.View; -import android.view.View.OnClickListener; -import android.widget.Button; - -public class RemoteServiceController extends Activity { - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - setContentView(R.layout.remote_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(). - // We use an action code here, instead of explictly supplying - // the component name, so that other packages can replace - // the service. - startService(new Intent( - "com.example.android.apis.app.REMOTE_SERVICE")); - } - }; - - 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( - "com.example.android.apis.app.REMOTE_SERVICE")); - } - }; -} diff --git a/samples/ApiDemos/src/com/example/android/apis/app/ServiceStartArguments.java b/samples/ApiDemos/src/com/example/android/apis/app/ServiceStartArguments.java index f4f9af1fb..f55144737 100644 --- a/samples/ApiDemos/src/com/example/android/apis/app/ServiceStartArguments.java +++ b/samples/ApiDemos/src/com/example/android/apis/app/ServiceStartArguments.java @@ -16,6 +16,7 @@ package com.example.android.apis.app; +import android.app.Activity; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; @@ -29,13 +30,16 @@ import android.os.Looper; import android.os.Message; import android.os.Process; import android.util.Log; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.Button; import android.widget.Toast; import com.example.android.apis.R; /** * This is an example of implementing an application service that runs locally - * in the same process as the application. The {@link ServiceStartArgumentsController} + * in the same process as the application. The {@link Controller} * class shows how to interact with the service. * *
Notice the use of the {@link NotificationManager} when interesting things @@ -44,7 +48,7 @@ import com.example.android.apis.R; * calling startActivity(). * *
For applications targeting Android 1.5 or beyond, you may want consider - * using the android.app.IntentService class, which takes care of all the + * using the {@link android.app.IntentService} class, which takes care of all the * work of creating the extra thread and dispatching commands to it. */ public class ServiceStartArguments extends Service { @@ -59,8 +63,7 @@ public class ServiceStartArguments extends Service { } @Override - public void handleMessage(Message msg) - { + public void handleMessage(Message msg) { Bundle arguments = (Bundle)msg.obj; String txt = arguments.getString("name"); @@ -105,7 +108,7 @@ public class ServiceStartArguments extends Service { // This is who should be launched if the user selects our persistent // notification. - mInvokeIntent = new Intent(this, ServiceStartArgumentsController.class); + mInvokeIntent = new Intent(this, Controller.class); // Start up the thread running the service. Note that we create a // separate thread because the service normally runs in the process's @@ -177,7 +180,7 @@ public class ServiceStartArguments extends Service { // The PendingIntent to launch our activity if the user selects this notification PendingIntent contentIntent = PendingIntent.getActivity(this, 0, - new Intent(this, AlarmService.class), 0); + new Intent(this, Controller.class), 0); // Set the info for the views that show in the notification panel. notification.setLatestEventInfo(this, getText(R.string.service_start_arguments_label), @@ -194,5 +197,76 @@ public class ServiceStartArguments extends Service { private void hideNotification() { mNM.cancel(R.string.service_created); } + + // ---------------------------------------------------------------------- + + /** + * Example of explicitly starting the {@link ServiceStartArguments}. + * + *
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.service_start_arguments_controller); + + // Watch for button clicks. + Button button = (Button)findViewById(R.id.start1); + button.setOnClickListener(mStart1Listener); + button = (Button)findViewById(R.id.start2); + button.setOnClickListener(mStart2Listener); + button = (Button)findViewById(R.id.start3); + button.setOnClickListener(mStart3Listener); + button = (Button)findViewById(R.id.startfail); + button.setOnClickListener(mStartFailListener); + button = (Button)findViewById(R.id.kill); + button.setOnClickListener(mKillListener); + } + + private OnClickListener mStart1Listener = new OnClickListener() { + public void onClick(View v) { + startService(new Intent(Controller.this, + ServiceStartArguments.class) + .putExtra("name", "One")); + } + }; + + private OnClickListener mStart2Listener = new OnClickListener() { + public void onClick(View v) { + startService(new Intent(Controller.this, + ServiceStartArguments.class) + .putExtra("name", "Two")); + } + }; + + private OnClickListener mStart3Listener = new OnClickListener() { + public void onClick(View v) { + startService(new Intent(Controller.this, + ServiceStartArguments.class) + .putExtra("name", "Three") + .putExtra("redeliver", true)); + } + }; + + private OnClickListener mStartFailListener = new OnClickListener() { + public void onClick(View v) { + startService(new Intent(Controller.this, + ServiceStartArguments.class) + .putExtra("name", "Failure") + .putExtra("fail", true)); + } + }; + + private OnClickListener mKillListener = new OnClickListener() { + public void onClick(View v) { + // This is to simulate the service being killed while it is + // running in the background. + Process.killProcess(Process.myPid()); + } + }; + } } diff --git a/samples/ApiDemos/src/com/example/android/apis/app/ServiceStartArgumentsController.java b/samples/ApiDemos/src/com/example/android/apis/app/ServiceStartArgumentsController.java deleted file mode 100644 index 9d79e2e05..000000000 --- a/samples/ApiDemos/src/com/example/android/apis/app/ServiceStartArgumentsController.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * 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; - -// Need the following import to get access to the app resources, since this -// class is in a sub-package. -import android.app.Activity; -import android.content.Intent; -import android.os.Bundle; -import android.os.Process; -import android.view.View; -import android.view.View.OnClickListener; -import android.widget.Button; - -import com.example.android.apis.R; - -/** - * Example of explicitly starting the {@link ServiceStartArguments}. - */ -public class ServiceStartArgumentsController extends Activity { - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - setContentView(R.layout.service_start_arguments_controller); - - // Watch for button clicks. - Button button = (Button)findViewById(R.id.start1); - button.setOnClickListener(mStart1Listener); - button = (Button)findViewById(R.id.start2); - button.setOnClickListener(mStart2Listener); - button = (Button)findViewById(R.id.start3); - button.setOnClickListener(mStart3Listener); - button = (Button)findViewById(R.id.startfail); - button.setOnClickListener(mStartFailListener); - button = (Button)findViewById(R.id.kill); - button.setOnClickListener(mKillListener); - } - - private OnClickListener mStart1Listener = new OnClickListener() { - public void onClick(View v) { - startService(new Intent(ServiceStartArgumentsController.this, - ServiceStartArguments.class) - .putExtra("name", "One")); - } - }; - - private OnClickListener mStart2Listener = new OnClickListener() { - public void onClick(View v) { - startService(new Intent(ServiceStartArgumentsController.this, - ServiceStartArguments.class) - .putExtra("name", "Two")); - } - }; - - private OnClickListener mStart3Listener = new OnClickListener() { - public void onClick(View v) { - startService(new Intent(ServiceStartArgumentsController.this, - ServiceStartArguments.class) - .putExtra("name", "Three") - .putExtra("redeliver", true)); - } - }; - - private OnClickListener mStartFailListener = new OnClickListener() { - public void onClick(View v) { - startService(new Intent(ServiceStartArgumentsController.this, - ServiceStartArguments.class) - .putExtra("name", "Failure") - .putExtra("fail", true)); - } - }; - - private OnClickListener mKillListener = new OnClickListener() { - public void onClick(View v) { - // This is to simulate the service being killed while it is - // running in the background. - Process.killProcess(Process.myPid()); - } - }; -} diff --git a/samples/ApiDemos/src/com/example/android/apis/app/_index.html b/samples/ApiDemos/src/com/example/android/apis/app/_index.html index 0ef5d9cc6..a64c650d7 100644 --- a/samples/ApiDemos/src/com/example/android/apis/app/_index.html +++ b/samples/ApiDemos/src/com/example/android/apis/app/_index.html @@ -41,55 +41,44 @@
android:process=":remote" to the service in the
- AndroidManifest.xml file.