Scott Main | 50e990c | 2012-06-21 17:14:39 -0700 | [diff] [blame] | 1 | page.title=Connecting to the Network |
| 2 | parent.title=Performing Network Operations |
| 3 | parent.link=index.html |
| 4 | |
| 5 | trainingnavtop=true |
| 6 | next.title=Managing Network Usage |
| 7 | next.link=managing.html |
| 8 | |
| 9 | @jd:body |
| 10 | |
| 11 | <div id="tb-wrapper"> |
| 12 | <div id="tb"> |
| 13 | |
| 14 | |
| 15 | |
| 16 | <h2>This lesson teaches you to</h2> |
| 17 | <ol> |
| 18 | <li><a href="#http-client">Choose an HTTP Client</a></li> |
| 19 | <li><a href="#connection">Check the Network Connection</a></li> |
| 20 | <li><a href="#AsyncTask">Perform Network Operations on a Separate Thread</a></li> |
| 21 | <li><a href="#download">Connect and Download Data</a></li> |
| 22 | <li><a href="#stream">Convert the InputStream to a String</a></li> |
| 23 | |
| 24 | </ol> |
| 25 | |
| 26 | <h2>You should also read</h2> |
| 27 | <ul> |
Katie McCormick | 1a89ae4 | 2014-03-18 17:13:50 -0700 | [diff] [blame] | 28 | <li><a href="{@docRoot}training/volley/index.html">Transmitting Network Data Using Volley</a></li> |
Scott Main | 50e990c | 2012-06-21 17:14:39 -0700 | [diff] [blame] | 29 | <li><a href="{@docRoot}training/monitoring-device-state/index.html">Optimizing Battery Life</a></li> |
| 30 | <li><a href="{@docRoot}training/efficient-downloads/index.html">Transferring Data Without Draining the Battery</a></li> |
| 31 | <li><a href="{@docRoot}guide/webapps/index.html">Web Apps Overview</a></li> |
| 32 | <li><a href="{@docRoot}guide/components/fundamentals.html">Application Fundamentals</a></li> |
| 33 | </ul> |
| 34 | |
| 35 | </div> |
| 36 | </div> |
| 37 | |
| 38 | <p>This lesson shows you how to implement a simple application that connects to |
| 39 | the network. It explains some of the best practices you should follow in |
| 40 | creating even the simplest network-connected app.</p> |
| 41 | |
| 42 | <p>Note that to perform the network operations described in this lesson, your |
| 43 | application manifest must include the following permissions:</p> |
| 44 | |
| 45 | <pre><uses-permission android:name="android.permission.INTERNET" /> |
| 46 | <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /></pre> |
| 47 | |
| 48 | |
| 49 | |
| 50 | <h2 id="http-client">Choose an HTTP Client</h2> |
| 51 | |
| 52 | <p>Most network-connected Android apps use HTTP to send and receive data. |
| 53 | Android includes two HTTP clients: {@link java.net.HttpURLConnection} and Apache |
| 54 | {@link org.apache.http.client.HttpClient}. Both support HTTPS, streaming uploads and downloads, configurable |
| 55 | timeouts, IPv6, and connection pooling. We recommend using {@link |
| 56 | java.net.HttpURLConnection} for applications targeted at Gingerbread and higher. For |
| 57 | more discussion of this topic, see the blog post <a |
| 58 | href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html" |
| 59 | >Android's HTTP Clients</a>.</p> |
| 60 | |
| 61 | <h2 id="connection">Check the Network Connection</h2> |
| 62 | |
| 63 | <p>Before your app attempts to connect to the network, it should check to see whether a |
| 64 | network connection is available using |
| 65 | {@link android.net.ConnectivityManager#getActiveNetworkInfo getActiveNetworkInfo()} |
| 66 | and {@link android.net.NetworkInfo#isConnected isConnected()}. |
| 67 | Remember, the device may be out of range of a |
| 68 | network, or the user may have disabled both Wi-Fi and mobile data access. |
| 69 | For more discussion of this topic, see the lesson <a |
Scott Main | f284d49 | 2012-07-31 09:46:52 -0700 | [diff] [blame] | 70 | href="{@docRoot}training/basics/network-ops/managing.html">Managing Network |
Scott Main | 50e990c | 2012-06-21 17:14:39 -0700 | [diff] [blame] | 71 | Usage</a>.</p> |
| 72 | |
| 73 | <pre> |
| 74 | public void myClickHandler(View view) { |
| 75 | ... |
| 76 | ConnectivityManager connMgr = (ConnectivityManager) |
| 77 | getSystemService(Context.CONNECTIVITY_SERVICE); |
| 78 | NetworkInfo networkInfo = connMgr.getActiveNetworkInfo(); |
| 79 | if (networkInfo != null && networkInfo.isConnected()) { |
| 80 | // fetch data |
| 81 | } else { |
| 82 | // display error |
| 83 | } |
| 84 | ... |
| 85 | }</pre> |
| 86 | |
| 87 | <h2 id="AsyncTask">Perform Network Operations on a Separate Thread</h2> |
| 88 | |
| 89 | <p>Network operations can involve unpredictable delays. To prevent this from |
| 90 | causing a poor user experience, always perform network operations on a separate |
| 91 | thread from the UI. The {@link android.os.AsyncTask} class provides one of the |
| 92 | simplest ways to fire off a new task from the UI thread. For more discussion of |
| 93 | this topic, see the blog post <a |
| 94 | href="http://android-developers.blogspot.com/2010/07/multithreading-for- |
| 95 | performance.html">Multithreading For Performance</a>.</p> |
| 96 | |
| 97 | |
| 98 | <p>In the following snippet, the <code>myClickHandler()</code> method invokes <code>new |
| 99 | DownloadWebpageTask().execute(stringUrl)</code>. The |
| 100 | <code>DownloadWebpageTask</code> class is a subclass of {@link |
| 101 | android.os.AsyncTask}. <code>DownloadWebpageTask</code> implements the following |
| 102 | {@link android.os.AsyncTask} methods:</p> |
| 103 | |
| 104 | <ul> |
| 105 | |
| 106 | <li>{@link android.os.AsyncTask#doInBackground doInBackground()} executes |
| 107 | the method <code>downloadUrl()</code>. It passes the web page URL as a |
| 108 | parameter. The method <code>downloadUrl()</code> fetches and processes the web |
| 109 | page content. When it finishes, it passes back a result string.</li> |
| 110 | |
| 111 | <li>{@link android.os.AsyncTask#onPostExecute onPostExecute()} takes the |
| 112 | returned string and displays it in the UI.</li> |
| 113 | |
| 114 | |
| 115 | </ul> |
| 116 | |
| 117 | <pre> |
| 118 | public class HttpExampleActivity extends Activity { |
| 119 | private static final String DEBUG_TAG = "HttpExample"; |
| 120 | private EditText urlText; |
| 121 | private TextView textView; |
| 122 | |
| 123 | @Override |
| 124 | public void onCreate(Bundle savedInstanceState) { |
| 125 | super.onCreate(savedInstanceState); |
| 126 | setContentView(R.layout.main); |
| 127 | urlText = (EditText) findViewById(R.id.myUrl); |
| 128 | textView = (TextView) findViewById(R.id.myText); |
| 129 | } |
| 130 | |
| 131 | // When user clicks button, calls AsyncTask. |
| 132 | // Before attempting to fetch the URL, makes sure that there is a network connection. |
| 133 | public void myClickHandler(View view) { |
| 134 | // Gets the URL from the UI's text field. |
| 135 | String stringUrl = urlText.getText().toString(); |
| 136 | ConnectivityManager connMgr = (ConnectivityManager) |
| 137 | getSystemService(Context.CONNECTIVITY_SERVICE); |
| 138 | NetworkInfo networkInfo = connMgr.getActiveNetworkInfo(); |
| 139 | if (networkInfo != null && networkInfo.isConnected()) { |
kmccormick | fad80f7 | 2013-04-03 18:16:15 -0700 | [diff] [blame] | 140 | new DownloadWebpageTask().execute(stringUrl); |
Scott Main | 50e990c | 2012-06-21 17:14:39 -0700 | [diff] [blame] | 141 | } else { |
| 142 | textView.setText("No network connection available."); |
| 143 | } |
| 144 | } |
| 145 | |
| 146 | // Uses AsyncTask to create a task away from the main UI thread. This task takes a |
| 147 | // URL string and uses it to create an HttpUrlConnection. Once the connection |
| 148 | // has been established, the AsyncTask downloads the contents of the webpage as |
| 149 | // an InputStream. Finally, the InputStream is converted into a string, which is |
| 150 | // displayed in the UI by the AsyncTask's onPostExecute method. |
kmccormick | fad80f7 | 2013-04-03 18:16:15 -0700 | [diff] [blame] | 151 | private class DownloadWebpageTask extends AsyncTask<String, Void, String> { |
Scott Main | 50e990c | 2012-06-21 17:14:39 -0700 | [diff] [blame] | 152 | @Override |
| 153 | protected String doInBackground(String... urls) { |
| 154 | |
| 155 | // params comes from the execute() call: params[0] is the url. |
| 156 | try { |
| 157 | return downloadUrl(urls[0]); |
| 158 | } catch (IOException e) { |
| 159 | return "Unable to retrieve web page. URL may be invalid."; |
| 160 | } |
| 161 | } |
| 162 | // onPostExecute displays the results of the AsyncTask. |
| 163 | @Override |
| 164 | protected void onPostExecute(String result) { |
| 165 | textView.setText(result); |
| 166 | } |
| 167 | } |
| 168 | ... |
| 169 | }</pre> |
| 170 | |
| 171 | <p>The sequence of events in this snippet is as follows:</p> |
| 172 | <ol> |
| 173 | |
| 174 | <li>When users click the button that invokes {@code myClickHandler()}, |
| 175 | the app passes |
| 176 | the specified URL to the {@link android.os.AsyncTask} subclass |
| 177 | <code>DownloadWebpageTask</code>.</li> |
| 178 | |
| 179 | <li>The {@link android.os.AsyncTask} method {@link |
| 180 | android.os.AsyncTask#doInBackground doInBackground()} calls the |
| 181 | <code>downloadUrl()</code> method. </li> |
| 182 | |
| 183 | <li>The <code>downloadUrl()</code> method takes a URL string as a parameter |
| 184 | and uses it to create a {@link java.net.URL} object.</li> |
| 185 | |
| 186 | <li>The {@link java.net.URL} object is used to establish an {@link |
| 187 | java.net.HttpURLConnection}.</li> |
| 188 | |
| 189 | <li>Once the connection has been established, the {@link |
| 190 | java.net.HttpURLConnection} object fetches the web page content as an {@link |
| 191 | java.io.InputStream}.</li> |
| 192 | |
| 193 | <li>The {@link java.io.InputStream} is passed to the <code>readIt()</code> |
| 194 | method, which converts the stream to a string.</li> |
| 195 | |
| 196 | <li>Finally, the {@link android.os.AsyncTask}'s {@link |
| 197 | android.os.AsyncTask#onPostExecute onPostExecute()} method displays the string |
| 198 | in the main activity's UI.</li> |
| 199 | |
| 200 | </ol> |
| 201 | |
| 202 | <h2 id="download">Connect and Download Data</h2> |
| 203 | |
| 204 | <p>In your thread that performs your network transactions, you can use |
| 205 | {@link java.net.HttpURLConnection} to perform a {@code GET} and download your data. |
| 206 | After you call {@code connect()}, you can get an {@link java.io.InputStream} of the data |
| 207 | by calling {@code getInputStream()}. |
| 208 | |
| 209 | <p>In the following snippet, the {@link android.os.AsyncTask#doInBackground |
| 210 | doInBackground()} method calls the method <code>downloadUrl()</code>. The |
| 211 | <code>downloadUrl()</code> method takes the given URL and uses it to connect to |
| 212 | the network via {@link java.net.HttpURLConnection}. Once a connection has been |
| 213 | established, the app uses the method <code>getInputStream()</code> to retrieve |
| 214 | the data as an {@link java.io.InputStream}.</p> |
| 215 | |
| 216 | <pre> |
| 217 | // Given a URL, establishes an HttpUrlConnection and retrieves |
| 218 | // the web page content as a InputStream, which it returns as |
| 219 | // a string. |
| 220 | private String downloadUrl(String myurl) throws IOException { |
| 221 | InputStream is = null; |
| 222 | // Only display the first 500 characters of the retrieved |
| 223 | // web page content. |
| 224 | int len = 500; |
| 225 | |
| 226 | try { |
| 227 | URL url = new URL(myurl); |
| 228 | HttpURLConnection conn = (HttpURLConnection) url.openConnection(); |
| 229 | conn.setReadTimeout(10000 /* milliseconds */); |
| 230 | conn.setConnectTimeout(15000 /* milliseconds */); |
| 231 | conn.setRequestMethod("GET"); |
| 232 | conn.setDoInput(true); |
| 233 | // Starts the query |
| 234 | conn.connect(); |
| 235 | int response = conn.getResponseCode(); |
| 236 | Log.d(DEBUG_TAG, "The response is: " + response); |
| 237 | is = conn.getInputStream(); |
| 238 | |
| 239 | // Convert the InputStream into a string |
| 240 | String contentAsString = readIt(is, len); |
| 241 | return contentAsString; |
| 242 | |
| 243 | // Makes sure that the InputStream is closed after the app is |
| 244 | // finished using it. |
| 245 | } finally { |
| 246 | if (is != null) { |
| 247 | is.close(); |
| 248 | } |
| 249 | } |
| 250 | }</pre> |
| 251 | |
| 252 | <p>Note that the method <code>getResponseCode()</code> returns the connection's |
| 253 | <a href="http://www.w3.org/Protocols/HTTP/HTRESP.html">status code</a>. This is |
| 254 | a useful way of getting additional information about the connection. A status |
| 255 | code of 200 indicates success.</p> |
| 256 | |
| 257 | <h2 id="stream">Convert the InputStream to a String</h2> |
| 258 | |
| 259 | <p>An {@link java.io.InputStream} is a readable source of bytes. Once you get an {@link java.io.InputStream}, |
| 260 | it's common to decode or convert it into a |
| 261 | target data type. For example, if you were downloading image data, you might |
| 262 | decode and display it like this:</p> |
| 263 | |
| 264 | <pre>InputStream is = null; |
| 265 | ... |
| 266 | Bitmap bitmap = BitmapFactory.decodeStream(is); |
| 267 | ImageView imageView = (ImageView) findViewById(R.id.image_view); |
| 268 | imageView.setImageBitmap(bitmap); |
| 269 | </pre> |
| 270 | |
| 271 | <p>In the example shown above, the {@link java.io.InputStream} represents the text of a |
| 272 | web page. This is how the example converts the {@link java.io.InputStream} to |
| 273 | a string so that the activity can display it in the UI:</p> |
| 274 | |
| 275 | <pre>// Reads an InputStream and converts it to a String. |
| 276 | public String readIt(InputStream stream, int len) throws IOException, UnsupportedEncodingException { |
| 277 | Reader reader = null; |
| 278 | reader = new InputStreamReader(stream, "UTF-8"); |
| 279 | char[] buffer = new char[len]; |
| 280 | reader.read(buffer); |
| 281 | return new String(buffer); |
| 282 | }</pre> |
| 283 | |
| 284 | |
| 285 | |