Scott Main | 50e990c | 2012-06-21 17:14:39 -0700 | [diff] [blame] | 1 | page.title=Session Initiation Protocol |
Joe Fernandez | 33baa5a | 2013-11-14 11:41:19 -0800 | [diff] [blame] | 2 | page.tags=sipmanager,sipprofile,sipaudiocall,telephony |
Scott Main | 50e990c | 2012-06-21 17:14:39 -0700 | [diff] [blame] | 3 | @jd:body |
| 4 | <div id="qv-wrapper"> |
| 5 | <div id="qv"> |
| 6 | <h2>In this document</h2> |
| 7 | <ol> |
| 8 | |
| 9 | <li><a href="#requirements">Requirements and Limitations</a></li> |
| 10 | <li><a href="#classes">Classes and Interfaces</a></li> |
| 11 | <li><a href="#manifest">Creating the Manifest</a></li> |
| 12 | <li><a href="#manager">Creating a SIP Manager</a></li> |
| 13 | <li><a href="#profiles">Registering with a SIP Server</a></li> |
| 14 | <li><a href="#audio">Making an Audio Call</a></li> |
| 15 | <li><a href="#receiving">Receiving Calls</a></li> |
| 16 | <li><a href="#testing">Testing SIP Applications</a></li> |
| 17 | </ol> |
| 18 | |
| 19 | <h2>Key classes</h2> |
| 20 | <ol> |
| 21 | <li>{@link android.net.sip.SipManager}</li> |
| 22 | <li>{@link android.net.sip.SipProfile}</li> |
| 23 | <li>{@link android.net.sip.SipAudioCall}</li> |
| 24 | |
| 25 | </ol> |
| 26 | |
| 27 | <h2>Related samples</h2> |
| 28 | <ol> |
| 29 | <li> <a href="{@docRoot}resources/samples/SipDemo/index.html"> SipDemo</a></li> |
| 30 | </ol> |
| 31 | </div> |
| 32 | </div> |
| 33 | |
| 34 | <p>Android provides an API that supports the Session Initiation Protocol (SIP). |
| 35 | This lets you add SIP-based internet telephony features to your applications. |
| 36 | Android includes a full SIP protocol stack and integrated call management |
| 37 | services that let applications easily set up outgoing and incoming voice calls, |
| 38 | without having to manage sessions, transport-level communication, or audio |
| 39 | record or playback directly.</p> |
| 40 | |
| 41 | <p>Here are examples of the types of applications that might use the SIP API:</p> |
| 42 | <ul> |
| 43 | <li>Video conferencing.</li> |
| 44 | <li>Instant messaging.</li> |
| 45 | </ul> |
| 46 | <h2 id="requirements">Requirements and Limitations</h2> |
| 47 | <p>Here are the requirements for developing a SIP application:</p> |
| 48 | <ul> |
| 49 | |
| 50 | <li>You must have a mobile device that is running Android 2.3 or higher. </li> |
| 51 | |
| 52 | <li>SIP runs over a wireless data connection, so your device must have a data |
| 53 | connection (with a mobile data service or Wi-Fi)</span>. This means that you |
| 54 | can't test on AVD—you can only test on a physical device. For details, see |
| 55 | <a href="#testing">Testing SIP Applications</a>.</li> |
| 56 | |
| 57 | <li>Each participant in the application's communication session must have a |
| 58 | SIP account. There are many different SIP providers that offer SIP accounts.</li> |
| 59 | </ul> |
| 60 | |
| 61 | |
| 62 | <h2 id="classes">SIP API Classes and Interfaces</h2> |
| 63 | |
| 64 | <p>Here is a summary of the classes and one interface |
| 65 | (<code>SipRegistrationListener</code>) that are included in the Android SIP |
| 66 | API:</p> |
| 67 | |
| 68 | <table> |
| 69 | <thead> |
| 70 | <tr> |
| 71 | <th>Class/Interface</th> |
| 72 | <th>Description</th> |
| 73 | </tr> |
| 74 | </thead> |
| 75 | <tbody> |
| 76 | <tr> |
| 77 | <td>{@link android.net.sip.SipAudioCall}</td> |
| 78 | <td>Handles an Internet audio call over SIP.</td> |
| 79 | </tr> |
| 80 | <tr> |
| 81 | <td>{@link android.net.sip.SipAudioCall.Listener}</td> |
| 82 | <td>Listener for events relating to a SIP call, such as when a call is being |
| 83 | received ("on ringing") or a call is outgoing ("on calling").</td> |
| 84 | </tr> |
| 85 | <tr> |
| 86 | <td>{@link android.net.sip.SipErrorCode}</td> |
| 87 | <td>Defines error codes returned during SIP actions.</td> |
| 88 | </tr> |
| 89 | <tr> |
| 90 | <td>{@link android.net.sip.SipManager}</td> |
| 91 | <td>Provides APIs for SIP tasks, such as initiating SIP connections, and provides access |
| 92 | to related SIP services.</td> |
| 93 | </tr> |
| 94 | <tr> |
| 95 | <td>{@link android.net.sip.SipProfile}</td> |
| 96 | <td>Defines a SIP profile, including a SIP account, domain and server information. |
| 97 | </td> |
| 98 | </tr> |
| 99 | <tr> |
| 100 | <td>{@link android.net.sip.SipProfile.Builder}</td> |
| 101 | <td>Helper class for creating a SipProfile.</td> |
| 102 | </tr> |
| 103 | <tr> |
| 104 | <td>{@link android.net.sip.SipSession}</td> |
| 105 | <td>Represents a SIP session that is associated with a SIP dialog or a standalone transaction |
| 106 | not within a dialog.</td> |
| 107 | </tr> |
| 108 | <tr> |
| 109 | <td>{@link android.net.sip.SipSession.Listener}</td> |
| 110 | <td>Listener for events relating to a SIP session, such as when a session is being registered |
| 111 | ("on registering") or a call is outgoing ("on calling"). </td> |
| 112 | </tr> |
| 113 | <tr> |
| 114 | <td>{@link android.net.sip.SipSession.State}</td> |
| 115 | <td>Defines SIP session states, such as "registering", "outgoing call", and "in call". </td> |
| 116 | </tr> |
| 117 | <tr> |
| 118 | <td>{@link android.net.sip.SipRegistrationListener}</td> |
| 119 | <td>An interface that is a listener for SIP registration events.</td> |
| 120 | </tr> |
| 121 | </tbody> |
| 122 | </table> |
| 123 | |
| 124 | <h2 id="manifest">Creating the Manifest</h2> |
| 125 | |
| 126 | <p>If you are developing an application that uses the SIP API, remember that the |
| 127 | feature is supported only on Android 2.3 (API level 9) and higher versions of |
| 128 | the platform. Also, among devices running Android 2.3 (API level 9) or higher, |
| 129 | not all devices will offer SIP support.</p> |
| 130 | |
| 131 | <p>To use SIP, add the following permissions to your application's manifest:</p> |
| 132 | <ul> |
| 133 | <li><code>android.permission.USE_SIP</code></li> |
| 134 | <li><code>android.permission.INTERNET</code></li> |
| 135 | </ul> |
| 136 | |
| 137 | <p> To ensure that your application can only be installed on devices that are |
| 138 | capable of supporting SIP, add the following to your application's |
| 139 | manifest:</p> |
| 140 | |
| 141 | <ul> |
| 142 | <li><code><uses-sdk android:minSdkVersion="9" /></code>. This |
| 143 | indicates that your application requires Android 2.3 or higher. For more |
| 144 | information, see <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#ApiLevels">API |
| 145 | Levels</a> and the documentation for the <a |
| 146 | href="{@docRoot}guide/topics/manifest/uses-sdk-element.html"><uses-sdk></a |
| 147 | > element.</li> |
| 148 | </ul> |
| 149 | |
| 150 | <p>To control how your application is filtered from devices that do not support |
| 151 | SIP (for example, on Google Play), add the following to your application's |
| 152 | manifest:</p> |
| 153 | |
| 154 | <ul> |
| 155 | |
| 156 | <li><code><uses-feature android:name="android.hardware.sip.voip" |
| 157 | /></code>. This states that your application uses the SIP API. The |
| 158 | declaration should include an <code>android:required</code> attribute that |
| 159 | indicates whether you want the application to be filtered from devices that do |
| 160 | not offer SIP support. Other <code><uses-feature></code> declarations |
| 161 | may also be needed, depending on your implementation. For more information, |
| 162 | see the documentation for the <a |
| 163 | href="{@docRoot}guide/topics/manifest/uses-feature-element.html"><uses- |
| 164 | feature></a> element.</li> |
| 165 | |
| 166 | </ul> |
| 167 | <p>If your application is designed to receive calls, you must also define a receiver ({@link android.content.BroadcastReceiver} subclass) in the application's manifest: </p> |
| 168 | |
| 169 | <ul> |
| 170 | <li><code><receiver android:name=".IncomingCallReceiver" android:label="Call Receiver"/></code></li> |
| 171 | </ul> |
| 172 | <p>Here are excerpts from the <strong>SipDemo</strong> manifest:</p> |
| 173 | |
| 174 | |
| 175 | |
| 176 | <pre><?xml version="1.0" encoding="utf-8"?> |
| 177 | <manifest xmlns:android="http://schemas.android.com/apk/res/android" |
| 178 | package="com.example.android.sip"> |
| 179 | ... |
| 180 | <receiver android:name=".IncomingCallReceiver" android:label="Call Receiver"/> |
| 181 | ... |
| 182 | <uses-sdk android:minSdkVersion="9" /> |
| 183 | <uses-permission android:name="android.permission.USE_SIP" /> |
| 184 | <uses-permission android:name="android.permission.INTERNET" /> |
| 185 | ... |
| 186 | <uses-feature android:name="android.hardware.sip.voip" android:required="true" /> |
| 187 | <uses-feature android:name="android.hardware.wifi" android:required="true" /> |
| 188 | <uses-feature android:name="android.hardware.microphone" android:required="true" /> |
| 189 | </manifest> |
| 190 | </pre> |
| 191 | |
| 192 | |
| 193 | <h2 id="manager">Creating a SipManager</h2> |
| 194 | |
| 195 | <p>To use the SIP API, your application must create a {@link |
| 196 | android.net.sip.SipManager} object. The {@link android.net.sip.SipManager} takes |
| 197 | care of the following in your application:</p> |
| 198 | |
| 199 | <ul> |
| 200 | <li>Initiating SIP sessions.</li> |
| 201 | <li>Initiating and receiving calls.</li> |
| 202 | <li>Registering and unregistering with a SIP provider.</li> |
| 203 | <li>Verifying session connectivity.</li> |
| 204 | </ul> |
| 205 | <p>You instantiate a new {@link android.net.sip.SipManager} as follows:</p> |
| 206 | <pre>public SipManager mSipManager = null; |
| 207 | ... |
| 208 | if(mSipManager == null) { |
| 209 | mSipManager = SipManager.newInstance(this); |
| 210 | }</pre> |
| 211 | <h2 id="profiles">Registering with a SIP Server</h2> |
| 212 | |
| 213 | <p>A typical Android SIP application involves one or more users, each of whom |
| 214 | has a SIP account. In an Android SIP application, each SIP account is |
| 215 | represented by a {@link android.net.sip.SipProfile} object.</p> |
| 216 | |
| 217 | <p>A {@link android.net.sip.SipProfile} defines a SIP profile, including a SIP |
| 218 | account, and domain and server information. The profile associated with the SIP |
| 219 | account on the device running the application is called the <em>local |
| 220 | profile</em>. The profile that the session is connected to is called the |
| 221 | <em>peer profile</em>. When your SIP application logs into the SIP server with |
| 222 | the local {@link android.net.sip.SipProfile}, this effectively registers the |
| 223 | device as the location to send SIP calls to for your SIP address.</p> |
| 224 | |
| 225 | <p>This section shows how to create a {@link android.net.sip.SipProfile}, |
| 226 | register it with a SIP server, and track registration events.</p> |
| 227 | |
| 228 | <p>You create a {@link android.net.sip.SipProfile} object as follows:</p> |
| 229 | <pre> |
| 230 | public SipProfile mSipProfile = null; |
| 231 | ... |
| 232 | |
| 233 | SipProfile.Builder builder = new SipProfile.Builder(username, domain); |
| 234 | builder.setPassword(password); |
| 235 | mSipProfile = builder.build();</pre> |
| 236 | |
| 237 | <p>The following code excerpt opens the local profile for making calls and/or |
| 238 | receiving generic SIP calls. The caller can make subsequent calls through |
| 239 | <code>mSipManager.makeAudioCall</code>. This excerpt also sets the action |
| 240 | <code>android.SipDemo.INCOMING_CALL</code>, which will be used by an intent |
| 241 | filter when the device receives a call (see <a href="#intent_filter">Setting up |
| 242 | an intent filter to receive calls</a>). This is the registration step:</p> |
| 243 | |
| 244 | <pre>Intent intent = new Intent(); |
| 245 | intent.setAction("android.SipDemo.INCOMING_CALL"); |
| 246 | PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, Intent.FILL_IN_DATA); |
| 247 | mSipManager.open(mSipProfile, pendingIntent, null);</pre> |
| 248 | |
| 249 | <p>Finally, this code sets a <code>SipRegistrationListener</code> on the {@link |
| 250 | android.net.sip.SipManager}. This tracks whether the {@link |
| 251 | android.net.sip.SipProfile} was successfully registered with your SIP service |
| 252 | provider:<br> |
| 253 | </p> |
| 254 | |
| 255 | <pre>mSipManager.setRegistrationListener(mSipProfile.getUriString(), new SipRegistrationListener() { |
| 256 | |
| 257 | public void onRegistering(String localProfileUri) { |
| 258 | updateStatus("Registering with SIP Server..."); |
| 259 | } |
| 260 | |
| 261 | public void onRegistrationDone(String localProfileUri, long expiryTime) { |
| 262 | updateStatus("Ready"); |
| 263 | } |
| 264 | |
| 265 | public void onRegistrationFailed(String localProfileUri, int errorCode, |
| 266 | String errorMessage) { |
| 267 | updateStatus("Registration failed. Please check settings."); |
| 268 | }</pre> |
| 269 | |
| 270 | |
| 271 | <p>When your application is done using a profile, it should close it to free |
| 272 | associated objects into memory and unregister the device from the server. For |
| 273 | example:</p> |
| 274 | |
| 275 | <pre>public void closeLocalProfile() { |
| 276 | if (mSipManager == null) { |
| 277 | return; |
| 278 | } |
| 279 | try { |
| 280 | if (mSipProfile != null) { |
| 281 | mSipManager.close(mSipProfile.getUriString()); |
| 282 | } |
| 283 | } catch (Exception ee) { |
| 284 | Log.d("WalkieTalkieActivity/onDestroy", "Failed to close local profile.", ee); |
| 285 | } |
| 286 | }</pre> |
| 287 | |
| 288 | <h2 id="audio">Making an Audio Call</h2> |
| 289 | <p>To make an audio call, you must have the following in place:</p> |
| 290 | <ul> |
| 291 | |
| 292 | <li>A {@link android.net.sip.SipProfile} that is making the call (the |
| 293 | "local profile"), and a valid SIP address to receive the call (the |
| 294 | "peer profile"). |
| 295 | |
| 296 | <li>A {@link android.net.sip.SipManager} object. </li> |
| 297 | </ul> |
| 298 | |
| 299 | <p>To make an audio call, you should set up a {@link |
| 300 | android.net.sip.SipAudioCall.Listener}. Much of the client's interaction with |
| 301 | the SIP stack happens through listeners. In this snippet, you see how the {@link |
| 302 | android.net.sip.SipAudioCall.Listener} sets things up after the call is |
| 303 | established:</p> |
| 304 | |
| 305 | <pre> |
| 306 | SipAudioCall.Listener listener = new SipAudioCall.Listener() { |
| 307 | |
| 308 | @Override |
| 309 | public void onCallEstablished(SipAudioCall call) { |
| 310 | call.startAudio(); |
| 311 | call.setSpeakerMode(true); |
| 312 | call.toggleMute(); |
| 313 | ... |
| 314 | } |
| 315 | |
| 316 | @Override |
| 317 | public void onCallEnded(SipAudioCall call) { |
| 318 | // Do something. |
| 319 | } |
| 320 | };</pre> |
| 321 | |
| 322 | <p>Once you've set up the {@link android.net.sip.SipAudioCall.Listener}, you can |
| 323 | make the call. The {@link android.net.sip.SipManager} method |
| 324 | <code>makeAudioCall</code> takes the following parameters:</p> |
| 325 | |
| 326 | <ul> |
| 327 | <li>A local SIP profile (the caller).</li> |
| 328 | <li>A peer SIP profile (the user being called).</li> |
| 329 | |
| 330 | <li>A {@link android.net.sip.SipAudioCall.Listener} to listen to the call |
| 331 | events from {@link android.net.sip.SipAudioCall}. This can be <code>null</code>, |
| 332 | but as shown above, the listener is used to set things up once the call is |
| 333 | established.</li> |
| 334 | |
| 335 | <li>The timeout value, in seconds.</li> |
| 336 | </ul> |
| 337 | <p>For example:</p> |
| 338 | <pre> call = mSipManager.makeAudioCall(mSipProfile.getUriString(), sipAddress, listener, 30);</pre> |
| 339 | |
| 340 | <h2 id="receiving">Receiving Calls</h2> |
| 341 | |
| 342 | <p>To receive calls, a SIP application must include a subclass of {@link |
| 343 | android.content.BroadcastReceiver} that has the ability to respond to an intent |
| 344 | indicating that there is an incoming call. Thus, you must do the following in |
| 345 | your application:</p> |
| 346 | |
| 347 | <ul> |
| 348 | <li>In <code>AndroidManifest.xml</code>, declare a |
| 349 | <code><receiver></code>. In <strong>SipDemo</strong>, this is |
| 350 | <code><receiver android:name=".IncomingCallReceiver" |
| 351 | android:label="Call Receiver"/></code>.</li> |
| 352 | |
| 353 | <li>Implement the receiver, which is a subclass of {@link |
| 354 | android.content.BroadcastReceiver}. In <strong>SipDemo</strong>, this is |
| 355 | <code>IncomingCallReceiver</code>.</li> |
| 356 | |
| 357 | <li>Initialize the local profile ({@link android.net.sip.SipProfile}) with a |
| 358 | pending intent that fires your receiver when someone calls the local profile. |
| 359 | </li> |
| 360 | |
| 361 | <li>Set up an intent filter that filters by the action that represents an |
| 362 | incoming call. In <strong>SipDemo</strong>, this action is |
| 363 | <code>android.SipDemo.INCOMING_CALL</code>. </li> |
| 364 | </ul> |
| 365 | <h4 id="BroadcastReceiver">Subclassing BroadcastReceiver</h4> |
| 366 | |
| 367 | <p>To receive calls, your SIP application must subclass {@link |
| 368 | android.content.BroadcastReceiver}. <span id="internal-source-marker_0.">The |
| 369 | Android system handles incoming SIP calls and broadcasts an "incoming |
| 370 | call"<code></code> intent (as defined by the application) when it receives |
| 371 | a call.</span> Here is the subclassed {@link android.content.BroadcastReceiver} |
| 372 | code from <strong>SipDemo</strong>. To see the full example, go to <a |
| 373 | href="{@docRoot}resources/samples/SipDemo/index.html">SipDemo sample</a>, which |
| 374 | is included in the SDK samples. For information on downloading and installing |
| 375 | the SDK samples, see <a |
| 376 | href="{@docRoot}resources/samples/get.html"> |
| 377 | Getting the Samples</a>. </p> |
| 378 | |
| 379 | <pre>/*** Listens for incoming SIP calls, intercepts and hands them off to WalkieTalkieActivity. |
| 380 | */ |
| 381 | public class IncomingCallReceiver extends BroadcastReceiver { |
| 382 | /** |
| 383 | * Processes the incoming call, answers it, and hands it over to the |
| 384 | * WalkieTalkieActivity. |
| 385 | * @param context The context under which the receiver is running. |
| 386 | * @param intent The intent being received. |
| 387 | */ |
| 388 | @Override |
| 389 | public void onReceive(Context context, Intent intent) { |
| 390 | SipAudioCall incomingCall = null; |
| 391 | try { |
| 392 | SipAudioCall.Listener listener = new SipAudioCall.Listener() { |
| 393 | @Override |
| 394 | public void onRinging(SipAudioCall call, SipProfile caller) { |
| 395 | try { |
| 396 | call.answerCall(30); |
| 397 | } catch (Exception e) { |
| 398 | e.printStackTrace(); |
| 399 | } |
| 400 | } |
| 401 | }; |
| 402 | WalkieTalkieActivity wtActivity = (WalkieTalkieActivity) context; |
| 403 | incomingCall = wtActivity.mSipManager.takeAudioCall(intent, listener); |
| 404 | incomingCall.answerCall(30); |
| 405 | incomingCall.startAudio(); |
| 406 | incomingCall.setSpeakerMode(true); |
| 407 | if(incomingCall.isMuted()) { |
| 408 | incomingCall.toggleMute(); |
| 409 | } |
| 410 | wtActivity.call = incomingCall; |
| 411 | wtActivity.updateStatus(incomingCall); |
| 412 | } catch (Exception e) { |
| 413 | if (incomingCall != null) { |
| 414 | incomingCall.close(); |
| 415 | } |
| 416 | } |
| 417 | } |
| 418 | } |
| 419 | </pre> |
| 420 | |
| 421 | <h4 id="intent_filter">Setting up an intent filter to receive calls</h4> |
| 422 | |
| 423 | <p>When the SIP service receives a new call, it sends out an intent with the |
| 424 | action string provided by the application. In SipDemo, this action string is |
| 425 | <code>android.SipDemo.INCOMING_CALL</code>. </p> |
| 426 | <p>This code excerpt from <strong>SipDemo</strong> shows how the {@link |
| 427 | android.net.sip.SipProfile} object gets created with a pending intent based on |
| 428 | the action string <code>android.SipDemo.INCOMING_CALL</code>. The |
| 429 | <code>PendingIntent</code> object will perform a broadcast when the {@link |
| 430 | android.net.sip.SipProfile} receives a call:</p> |
| 431 | |
| 432 | <pre> |
| 433 | public SipManager mSipManager = null; |
| 434 | public SipProfile mSipProfile = null; |
| 435 | ... |
| 436 | |
| 437 | Intent intent = new Intent(); |
| 438 | intent.setAction("android.SipDemo.INCOMING_CALL"); |
| 439 | PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, Intent.FILL_IN_DATA); |
| 440 | mSipManager.open(mSipProfile, pendingIntent, null);</pre> |
| 441 | |
| 442 | <p>The broadcast will be intercepted by the intent filter, which will then fire |
| 443 | the receiver (<code>IncomingCallReceiver</code>). You can specify an intent |
| 444 | filter in your application's manifest file, or do it in code as in the <strong>SipDemo</strong> |
| 445 | sample application's <code>onCreate()</code> method |
| 446 | of the application's <code>Activity</code>:</p> |
| 447 | |
| 448 | <pre> |
| 449 | public class WalkieTalkieActivity extends Activity implements View.OnTouchListener { |
| 450 | ... |
| 451 | public IncomingCallReceiver callReceiver; |
| 452 | ... |
| 453 | |
| 454 | @Override |
| 455 | public void onCreate(Bundle savedInstanceState) { |
| 456 | |
| 457 | IntentFilter filter = new IntentFilter(); |
| 458 | filter.addAction("android.SipDemo.INCOMING_CALL"); |
| 459 | callReceiver = new IncomingCallReceiver(); |
| 460 | this.registerReceiver(callReceiver, filter); |
| 461 | ... |
| 462 | } |
| 463 | ... |
| 464 | } |
| 465 | </pre> |
| 466 | |
| 467 | |
| 468 | <h2 id="testing">Testing SIP Applications</h2> |
| 469 | |
| 470 | <p>To test SIP applications, you need the following:</p> |
| 471 | <ul> |
| 472 | <li>A mobile device that is running Android 2.3 or higher. SIP runs over |
| 473 | wireless, so you must test on an actual device. Testing on AVD won't work.</li> |
| 474 | <li>A SIP account. There are many different SIP providers that offer SIP accounts.</li> |
| 475 | <li>If you are placing a call, it must also be to a valid SIP account. </li> |
| 476 | </ul> |
| 477 | <p>To test a SIP application:</p> |
| 478 | <ol> |
| 479 | |
| 480 | <li>On your device, connect to wireless (<strong>Settings > Wireless & networks |
| 481 | > Wi-Fi > Wi-Fi settings</strong>)</li> |
| 482 | <li>Set up your mobile device for testing, as described in <a |
| 483 | href="{@docRoot}tools/device.html">Developing on a Device</a>.</li> |
| 484 | <li>Run your application on your mobile device, as described in <a |
| 485 | href="{@docRoot}tools/device.html">Developing on a Device</a>.</li> |
| 486 | |
| 487 | <li>If you are using Eclipse, you can view the application log output in Eclipse |
| 488 | using LogCat (<strong>Window > Show View > Other > Android > |
| 489 | LogCat</strong>).</li> |
| 490 | </ol> |
| 491 | |