`

android执行网络操作

 
阅读更多



本篇我们会介绍连接到网络中涉及的基本任务,监测的网络连接(包括连接更改),并给予用户控制应用程序的网络使用情况。还介绍了如何解析和使用XML数据。

这个类包含一个示例应用程序来说明如何执行常见的网络操作。您可以下载示例(在右边),并用它作为自己的应用程序源代码的可重用代码。本章的重点有三:

1.连接到网络

2.管理网络的使用

3.解析XML数据

一、连接到网络

在mainfest中声明权限,代码如下:

Java代码
  1. <uses-permissionandroid:name="android.permission.INTERNET"/>
  2. <uses-permissionandroid:name="android.permission.ACCESS_NETWORK_STATE"/>

选择http客户端

大多数联网的Android应用程序使用HTTP来发送和接收数据。Android包括两个HTTP客户:HttpURLConnection HttpClient和Apache。都支持HTTPS,流媒体上传和下载,可配置的超时,IPv6,和连接池。我们建议使用HttpURLConnection目标应用程序。

检查网络连接

在你的应用程序尝试连接到网络,它应该检查是否一个网络连接可用使用getActiveNetworkInfo()和一个()。记住,这个装置可能范围的一个网络,或用户可能已经禁用wi - fi和移动数据访问。

Java代码
  1. publicvoidmyClickHandler(Viewview){
  2. ...
  3. ConnectivityManagerconnMgr=(ConnectivityManager)
  4. getSystemService(Context.CONNECTIVITY_SERVICE);
  5. NetworkInfonetworkInfo=connMgr.getActiveNetworkInfo();
  6. if(networkInfo!=null&&networkInfo.isConnected()){
  7. //fetchdata
  8. }else{
  9. //displayerror
  10. }
  11. ...
  12. }

在单独线程中执行网络操作

网络操作可以包括不可预测的延迟。为了防止这种导致一个糟糕的用户体验,总是执行网络操作在一个单独的线程。

Java代码
  1. publicclassHttpExampleActivityextendsActivity{
  2. privatestaticfinalStringDEBUG_TAG="HttpExample";
  3. privateEditTexturlText;
  4. privateTextViewtextView;
  5. @Override
  6. publicvoidonCreate(BundlesavedInstanceState){
  7. super.onCreate(savedInstanceState);
  8. setContentView(R.layout.main);
  9. urlText=(EditText)findViewById(R.id.myUrl);
  10. textView=(TextView)findViewById(R.id.myText);
  11. }
  12. //Whenuserclicksbutton,callsAsyncTask.
  13. //BeforeattemptingtofetchtheURL,makessurethatthereisanetworkconnection.
  14. publicvoidmyClickHandler(Viewview){
  15. //GetstheURLfromtheUI'stextfield.
  16. StringstringUrl=urlText.getText().toString();
  17. ConnectivityManagerconnMgr=(ConnectivityManager)
  18. getSystemService(Context.CONNECTIVITY_SERVICE);
  19. NetworkInfonetworkInfo=connMgr.getActiveNetworkInfo();
  20. if(networkInfo!=null&&networkInfo.isConnected()){
  21. newDownloadWebpageText().execute(stringUrl);
  22. }else{
  23. textView.setText("Nonetworkconnectionavailable.");
  24. }
  25. }
  26. //UsesAsyncTasktocreateataskawayfromthemainUIthread.Thistasktakesa
  27. //URLstringandusesittocreateanHttpUrlConnection.Oncetheconnection
  28. //hasbeenestablished,theAsyncTaskdownloadsthecontentsofthewebpageas
  29. //anInputStream.Finally,theInputStreamisconvertedintoastring,whichis
  30. //displayedintheUIbytheAsyncTask'sonPostExecutemethod.
  31. privateclassDownloadWebpageTextextendsAsyncTask{
  32. @Override
  33. protectedStringdoInBackground(String...urls){
  34. //paramscomesfromtheexecute()call:params[0]istheurl.
  35. try{
  36. returndownloadUrl(urls[0]);
  37. }catch(IOExceptione){
  38. return"Unabletoretrievewebpage.URLmaybeinvalid.";
  39. }
  40. }
  41. //onPostExecutedisplaystheresultsoftheAsyncTask.
  42. @Override
  43. protectedvoidonPostExecute(Stringresult){
  44. textView.setText(result);
  45. }
  46. }
  47. ...
  48. }

连接和下载数据

在你的线程执行您的网络交易,你可以使用HttpURLConnection来执行一个GET和下载数据。在您调用connect(),你可以得到一个InputStream的数据通过调用getInputStream()。

Java代码
  1. //GivenaURL,establishesanHttpUrlConnectionandretrieves
  2. //thewebpagecontentasaInputStream,whichitreturnsas
  3. //astring.
  4. privateStringdownloadUrl(Stringmyurl)throwsIOException{
  5. InputStreamis=null;
  6. //Onlydisplaythefirst500charactersoftheretrieved
  7. //webpagecontent.
  8. intlen=500;
  9. try{
  10. URLurl=newURL(myurl);
  11. HttpURLConnectionconn=(HttpURLConnection)url.openConnection();
  12. conn.setReadTimeout(10000/*milliseconds*/);
  13. conn.setConnectTimeout(15000/*milliseconds*/);
  14. conn.setRequestMethod("GET");
  15. conn.setDoInput(true);
  16. //Startsthequery
  17. conn.connect();
  18. intresponse=conn.getResponseCode();
  19. Log.d(DEBUG_TAG,"Theresponseis:"+response);
  20. is=conn.getInputStream();
  21. //ConverttheInputStreamintoastring
  22. StringcontentAsString=readIt(is,len);
  23. returncontentAsString;
  24. //MakessurethattheInputStreamisclosedaftertheappis
  25. //finishedusingit.
  26. }finally{
  27. if(is!=null){
  28. is.close();
  29. }
  30. }
  31. }

getResponseCode()返回连接的状态码。这是一种有用的方式获得一些额外的信息的连接。一个200的状态代码表示成功。

转换InputStreamString

Java代码
  1. //ReadsanInputStreamandconvertsittoaString.
  2. publicStringreadIt(InputStreamstream,intlen)throwsIOException,UnsupportedEncodingException{
  3. Readerreader=null;
  4. reader=newInputStreamReader(stream,"UTF-8");
  5. char[]buffer=newchar[len];
  6. reader.read(buffer);
  7. returnnewString(buffer);
  8. }

二、管理网络

检查设备的网络连接

一个设备可以有各种类型的网络连接。这节课的重点是使用wi - fi或手机或网络连接,这个代码片段测试网络连接wi - fi和移动。它确定这些网络接口是可用的或连接的(即网络连接是否存在,如果可以建立套接字和传递数据)

Java代码
  1. privatestaticfinalStringDEBUG_TAG="NetworkStatusExample";
  2. ...
  3. ConnectivityManagerconnMgr=(ConnectivityManager)
  4. getSystemService(Context.CONNECTIVITY_SERVICE);
  5. NetworkInfonetworkInfo=connMgr.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
  6. booleanisWifiConn=networkInfo.isConnected();
  7. networkInfo=connMgr.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
  8. booleanisMobileConn=networkInfo.isConnected();
  9. Log.d(DEBUG_TAG,"Wificonnected:"+isWifiConn);
  10. Log.d(DEBUG_TAG,"Mobileconnected:"+isMobileConn);

管理网络的使用

您可以实现一个首选项活动,让用户明确控制应用程序的使用网络资源。例如:1.你可能允许用户上传的视频只有当设备被连接到wi - fi网络。2.你可能会同步(或没有)根据特定标准如网络可用性、时间间隔,等等。

编写一个应用程序,支持网络访问和管理网络的使用,你的清单必须有正确的权限和意图过滤器。

在样例应用程序中,这个规定了SettingsActivity,将显示一个UI让用户知道何时可以进行下载操作。

Xml代码
  1. <?xmlversion="1.0"encoding="utf-8"?>
  2. <manifestxmlns:android="http://schemas.android.com/apk/res/android"
  3. package="com.example.android.networkusage"
  4. ...>
  5. <uses-sdkandroid:minSdkVersion="4"
  6. android:targetSdkVersion="14"/>
  7. <uses-permissionandroid:name="android.permission.INTERNET"/>
  8. <uses-permissionandroid:name="android.permission.ACCESS_NETWORK_STATE"/>
  9. <application
  10. ...>
  11. ...
  12. <activityandroid:label="SettingsActivity"android:name=".SettingsActivity">
  13. <intent-filter>
  14. <actionandroid:name="android.intent.action.MANAGE_NETWORK_USAGE"/>
  15. <categoryandroid:name="android.intent.category.DEFAULT"/>
  16. </intent-filter>
  17. </activity>
  18. </application>
  19. </manifest>

Java代码
  1. publicclassSettingsActivityextendsPreferenceActivityimplementsOnSharedPreferenceChangeListener{
  2. @Override
  3. protectedvoidonCreate(BundlesavedInstanceState){
  4. super.onCreate(savedInstanceState);
  5. //LoadstheXMLpreferencesfile
  6. addPreferencesFromResource(R.xml.preferences);
  7. }
  8. @Override
  9. protectedvoidonResume(){
  10. super.onResume();
  11. //Registersalistenerwheneverakeychanges
  12. getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
  13. }
  14. @Override
  15. protectedvoidonPause(){
  16. super.onPause();
  17. //UnregistersthelistenersetinonResume().
  18. //It'sbestpracticetounregisterlistenerswhenyourappisn'tusingthemtocutdownon
  19. //unnecessarysystemoverhead.YoudothisinonPause().
  20. getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
  21. }
  22. //Whentheuserchangesthepreferencesselection,
  23. //onSharedPreferenceChanged()restartsthemainactivityasanew
  24. //task.SetsthetherefreshDisplayflagto"true"toindicatethat
  25. //themainactivityshouldupdateitsdisplay.
  26. //ThemainactivityqueriesthePreferenceManagertogetthelatestsettings.
  27. @Override
  28. publicvoidonSharedPreferenceChanged(SharedPreferencessharedPreferences,Stringkey){
  29. //SetsrefreshDisplaytotruesothatwhentheuserreturnstothemain
  30. //activity,thedisplayrefreshestoreflectthenewsettings.
  31. NetworkActivity.refreshDisplay=true;
  32. }
  33. }

响应网络变动

如果有一个匹配发生在设置和设备的网络连接(例如,如果设置为“wi - fi”和设备有一个wi - fi连接)之间,应用程序下载提继续并刷新显示

Java代码
  1. publicclassNetworkActivityextendsActivity{
  2. publicstaticfinalStringWIFI="Wi-Fi";
  3. publicstaticfinalStringANY="Any";
  4. privatestaticfinalStringURL="http://stackoverflow.com/feeds/tag?tagnames=android&sort=newest";
  5. //WhetherthereisaWi-Ficonnection.
  6. privatestaticbooleanwifiConnected=false;
  7. //Whetherthereisamobileconnection.
  8. privatestaticbooleanmobileConnected=false;
  9. //Whetherthedisplayshouldberefreshed.
  10. publicstaticbooleanrefreshDisplay=true;
  11. //Theuser'scurrentnetworkpreferencesetting.
  12. publicstaticStringsPref=null;
  13. //TheBroadcastReceiverthattracksnetworkconnectivitychanges.
  14. privateNetworkReceiverreceiver=newNetworkReceiver();
  15. @Override
  16. publicvoidonCreate(BundlesavedInstanceState){
  17. super.onCreate(savedInstanceState);
  18. //RegistersBroadcastReceivertotracknetworkconnectionchanges.
  19. IntentFilterfilter=newIntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
  20. receiver=newNetworkReceiver();
  21. this.registerReceiver(receiver,filter);
  22. }
  23. @Override
  24. publicvoidonDestroy(){
  25. super.onDestroy();
  26. //UnregistersBroadcastReceiverwhenappisdestroyed.
  27. if(receiver!=null){
  28. this.unregisterReceiver(receiver);
  29. }
  30. }
  31. //Refreshesthedisplayifthenetworkconnectionandthe
  32. //prefsettingsallowit.
  33. @Override
  34. publicvoidonStart(){
  35. super.onStart();
  36. //Getstheuser'snetworkpreferencesettings
  37. SharedPreferencessharedPrefs=PreferenceManager.getDefaultSharedPreferences(this);
  38. //Retrievesastringvalueforthepreferences.Thesecondparameter
  39. //isthedefaultvaluetouseifapreferencevalueisnotfound.
  40. sPref=sharedPrefs.getString("listPref","Wi-Fi");
  41. updateConnectedFlags();
  42. if(refreshDisplay){
  43. loadPage();
  44. }
  45. }
  46. //ChecksthenetworkconnectionandsetsthewifiConnectedandmobileConnected
  47. //variablesaccordingly.
  48. publicvoidupdateConnectedFlags(){
  49. ConnectivityManagerconnMgr=(ConnectivityManager)
  50. getSystemService(Context.CONNECTIVITY_SERVICE);
  51. NetworkInfoactiveInfo=connMgr.getActiveNetworkInfo();
  52. if(activeInfo!=null&&activeInfo.isConnected()){
  53. wifiConnected=activeInfo.getType()==ConnectivityManager.TYPE_WIFI;
  54. mobileConnected=activeInfo.getType()==ConnectivityManager.TYPE_MOBILE;
  55. }else{
  56. wifiConnected=false;
  57. mobileConnected=false;
  58. }
  59. }
  60. //UsesAsyncTasksubclasstodownloadtheXMLfeedfromstackoverflow.com.
  61. publicvoidloadPage(){
  62. if(((sPref.equals(ANY))&&(wifiConnected||mobileConnected))
  63. ||((sPref.equals(WIFI))&&(wifiConnected))){
  64. //AsyncTasksubclass
  65. newDownloadXmlTask().execute(URL);
  66. }else{
  67. showErrorPage();
  68. }
  69. }
  70. ...
  71. }

检测网络连接变化

Java代码
  1. publicclassNetworkReceiverextendsBroadcastReceiver{
  2. @Override
  3. publicvoidonReceive(Contextcontext,Intentintent){
  4. ConnectivityManagerconn=(ConnectivityManager)
  5. context.getSystemService(Context.CONNECTIVITY_SERVICE);
  6. NetworkInfonetworkInfo=conn.getActiveNetworkInfo();
  7. //Checkstheuserprefsandthenetworkconnection.Basedontheresult,decideswhether
  8. //torefreshthedisplayorkeepthecurrentdisplay.
  9. //IftheuserprefisWi-Fionly,checkstoseeifthedevicehasaWi-Ficonnection.
  10. if(WIFI.equals(sPref)&&networkInfo!=null&&networkInfo.getType()==ConnectivityManager.TYPE_WIFI){
  11. //IfdevicehasitsWi-Ficonnection,setsrefreshDisplay
  12. //totrue.Thiscausesthedisplaytoberefreshedwhentheuser
  13. //returnstotheapp.
  14. refreshDisplay=true;
  15. Toast.makeText(context,R.string.wifi_connected,Toast.LENGTH_SHORT).show();
  16. //IfthesettingisANYnetworkandthereisanetworkconnection
  17. //(whichbyprocessofeliminationwouldbemobile),setsrefreshDisplaytotrue.
  18. }elseif(ANY.equals(sPref)&&networkInfo!=null){
  19. refreshDisplay=true;
  20. //Otherwise,theappcan'tdownloadcontent--eitherbecausethereisnonetwork
  21. //connection(mobileorWi-Fi),orbecausetheprefsettingisWIFI,andthere
  22. //isnoWi-Ficonnection.
  23. //SetsrefreshDisplaytofalse.
  24. }else{
  25. refreshDisplay=false;
  26. Toast.makeText(context,R.string.lost_connection,Toast.LENGTH_SHORT).show();
  27. }
  28. }

三、解析xml

上传和解析XML数据是很常见的任务,网络连接应用程序。这一课解释了如何解析XML文档并使用他们的数据

选择转换器

我们建议XmlPullParser,这是一种高效且可维护的方式来解析XML在Android里。

分析需求

Xml代码
  1. <?xmlversion="1.0"encoding="utf-8"?>
  2. <feedxmlns="http://www.w3.org/2005/Atom"xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule"...">
  3. <titletype="text">newestquestionstaggedandroid-StackOverflow</title>
  4. ...
  5. <entry>
  6. ...
  7. </entry>
  8. <entry>
  9. <id>http://stackoverflow.com/q/9439999</id>
  10. <re:rankscheme="http://stackoverflow.com">0</re:rank>
  11. <titletype="text">Whereismydatafile?</title>
  12. <categoryscheme="http://stackoverflow.com/feeds/tag?tagnames=android&sort=newest/tags"term="android"/>
  13. <categoryscheme="http://stackoverflow.com/feeds/tag?tagnames=android&sort=newest/tags"term="file"/>
  14. <author>
  15. <name>cliff2310</name>
  16. <uri>http://stackoverflow.com/users/1128925</uri>
  17. </author>
  18. <linkrel="alternate"href="http://stackoverflow.com/questions/9439999/where-is-my-data-file"/>
  19. <published>2012-02-25T00:30:54Z</published>
  20. <updated>2012-02-25T00:30:54Z</updated>
  21. <summarytype="html">
  22. <p>IhaveanApplicationthatrequiresadatafile...</p>
  23. </summary>
  24. </entry>
  25. <entry>
  26. ...
  27. </entry>
  28. ...
  29. </feed>

实例化转化器

Java代码
  1. publicclassStackOverflowXmlParser{
  2. //Wedon'tusenamespaces
  3. privatestaticfinalStringns=null;
  4. publicListparse(InputStreamin)throwsXmlPullParserException,IOException{
  5. try{
  6. XmlPullParserparser=Xml.newPullParser();
  7. parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES,false);
  8. parser.setInput(in,null);
  9. parser.nextTag();
  10. returnreadFeed(parser);
  11. }finally{
  12. in.close();
  13. }
  14. }
  15. ...
  16. }
  17. 读取xml
  18. privateListreadFeed(XmlPullParserparser)throwsXmlPullParserException,IOException{
  19. Listentries=newArrayList();
  20. parser.require(XmlPullParser.START_TAG,ns,"feed");
  21. while(parser.next()!=XmlPullParser.END_TAG){
  22. if(parser.getEventType()!=XmlPullParser.START_TAG){
  23. continue;
  24. }
  25. Stringname=parser.getName();
  26. //Startsbylookingfortheentrytag
  27. if(name.equals("entry")){
  28. entries.add(readEntry(parser));
  29. }else{
  30. skip(parser);
  31. }
  32. }
  33. returnentries;
  34. }

下面这个代码片段展示了如何解析器解析条目、标题、链接和总结:

Java代码
  1. publicstaticclassEntry{
  2. publicfinalStringtitle;
  3. publicfinalStringlink;
  4. publicfinalStringsummary;
  5. privateEntry(Stringtitle,Stringsummary,Stringlink){
  6. this.title=title;
  7. this.summary=summary;
  8. this.link=link;
  9. }
  10. }
  11. //Parsesthecontentsofanentry.Ifitencountersatitle,summary,orlinktag,handsthemoff
  12. //totheirrespective"read"methodsforprocessing.Otherwise,skipsthetag.
  13. privateEntryreadEntry(XmlPullParserparser)throwsXmlPullParserException,IOException{
  14. parser.require(XmlPullParser.START_TAG,ns,"entry");
  15. Stringtitle=null;
  16. Stringsummary=null;
  17. Stringlink=null;
  18. while(parser.next()!=XmlPullParser.END_TAG){
  19. if(parser.getEventType()!=XmlPullParser.START_TAG){
  20. continue;
  21. }
  22. Stringname=parser.getName();
  23. if(name.equals("title")){
  24. title=readTitle(parser);
  25. }elseif(name.equals("summary")){
  26. summary=readSummary(parser);
  27. }elseif(name.equals("link")){
  28. link=readLink(parser);
  29. }else{
  30. skip(parser);
  31. }
  32. }
  33. returnnewEntry(title,summary,link);
  34. }
  35. //Processestitletagsinthefeed.
  36. privateStringreadTitle(XmlPullParserparser)throwsIOException,XmlPullParserException{
  37. parser.require(XmlPullParser.START_TAG,ns,"title");
  38. Stringtitle=readText(parser);
  39. parser.require(XmlPullParser.END_TAG,ns,"title");
  40. returntitle;
  41. }
  42. //Processeslinktagsinthefeed.
  43. privateStringreadLink(XmlPullParserparser)throwsIOException,XmlPullParserException{
  44. Stringlink="";
  45. parser.require(XmlPullParser.START_TAG,ns,"link");
  46. Stringtag=parser.getName();
  47. StringrelType=parser.getAttributeValue(null,"rel");
  48. if(tag.equals("link")){
  49. if(relType.equals("alternate")){
  50. link=parser.getAttributeValue(null,"href");
  51. parser.nextTag();
  52. }
  53. }
  54. parser.require(XmlPullParser.END_TAG,ns,"link");
  55. returnlink;
  56. }
  57. //Processessummarytagsinthefeed.
  58. privateStringreadSummary(XmlPullParserparser)throwsIOException,XmlPullParserException{
  59. parser.require(XmlPullParser.START_TAG,ns,"summary");
  60. Stringsummary=readText(parser);
  61. parser.require(XmlPullParser.END_TAG,ns,"summary");
  62. returnsummary;
  63. }
  64. //Forthetagstitleandsummary,extractstheirtextvalues.
  65. privateStringreadText(XmlPullParserparser)throwsIOException,XmlPullParserException{
  66. Stringresult="";
  67. if(parser.next()==XmlPullParser.TEXT){
  68. result=parser.getText();
  69. parser.nextTag();
  70. }
  71. returnresult;
  72. }
  73. ...
  74. }

跳过无用的标签

Java代码
  1. privatevoidskip(XmlPullParserparser)throwsXmlPullParserException,IOException{
  2. if(parser.getEventType()!=XmlPullParser.START_TAG){
  3. thrownewIllegalStateException();
  4. }
  5. intdepth=1;
  6. while(depth!=0){
  7. switch(parser.next()){
  8. caseXmlPullParser.END_TAG:
  9. depth--;
  10. break;
  11. caseXmlPullParser.START_TAG:
  12. depth++;
  13. break;
  14. }
  15. }
  16. }

使用xml数据

Java代码
  1. publicclassNetworkActivityextendsActivity{
  2. publicstaticfinalStringWIFI="Wi-Fi";
  3. publicstaticfinalStringANY="Any";
  4. privatestaticfinalStringURL="http://stackoverflow.com/feeds/tag?tagnames=android&sort=newest";
  5. //WhetherthereisaWi-Ficonnection.
  6. privatestaticbooleanwifiConnected=false;
  7. //Whetherthereisamobileconnection.
  8. privatestaticbooleanmobileConnected=false;
  9. //Whetherthedisplayshouldberefreshed.
  10. publicstaticbooleanrefreshDisplay=true;
  11. publicstaticStringsPref=null;
  12. ...
  13. //UsesAsyncTasktodownloadtheXMLfeedfromstackoverflow.com.
  14. publicvoidloadPage(){
  15. if((sPref.equals(ANY))&&(wifiConnected||mobileConnected)){
  16. newDownloadXmlTask().execute(URL);
  17. }
  18. elseif((sPref.equals(WIFI))&&(wifiConnected)){
  19. newDownloadXmlTask().execute(URL);
  20. }else{
  21. //showerror
  22. }
  23. }

动态下载xml

Java代码
  1. //ImplementationofAsyncTaskusedtodownloadXMLfeedfromstackoverflow.com.
  2. privateclassDownloadXmlTaskextendsAsyncTask<String,Void,String>{
  3. @Override
  4. protectedStringdoInBackground(String...urls){
  5. try{
  6. returnloadXmlFromNetwork(urls[0]);
  7. }catch(IOExceptione){
  8. returngetResources().getString(R.string.connection_error);
  9. }catch(XmlPullParserExceptione){
  10. returngetResources().getString(R.string.xml_error);
  11. }
  12. }
  13. @Override
  14. protectedvoidonPostExecute(Stringresult){
  15. setContentView(R.layout.main);
  16. //DisplaystheHTMLstringintheUIviaaWebView
  17. WebViewmyWebView=(WebView)findViewById(R.id.webview);
  18. myWebView.loadData(result,"text/html",null);
  19. }
  20. }

加载xml

Java代码
  1. //UploadsXMLfromstackoverflow.com,parsesit,andcombinesitwith
  2. //HTMLmarkup.ReturnsHTMLstring.
  3. privateStringloadXmlFromNetwork(StringurlString)throwsXmlPullParserException,IOException{
  4. InputStreamstream=null;
  5. //Instantiatetheparser
  6. StackOverflowXmlParserstackOverflowXmlParser=newStackOverflowXmlParser();
  7. List<Entry>entries=null;
  8. Stringtitle=null;
  9. Stringurl=null;
  10. Stringsummary=null;
  11. CalendarrightNow=Calendar.getInstance();
  12. DateFormatformatter=newSimpleDateFormat("MMMddh:mmaa");
  13. //Checkswhethertheusersetthepreferencetoincludesummarytext
  14. SharedPreferencessharedPrefs=PreferenceManager.getDefaultSharedPreferences(this);
  15. booleanpref=sharedPrefs.getBoolean("summaryPref",false);
  16. StringBuilderhtmlString=newStringBuilder();
  17. htmlString.append("<h3>"+getResources().getString(R.string.page_title)+"</h3>");
  18. htmlString.append("<em>"+getResources().getString(R.string.updated)+""+
  19. formatter.format(rightNow.getTime())+"</em>");
  20. try{
  21. stream=downloadUrl(urlString);
  22. entries=stackOverflowXmlParser.parse(stream);
  23. //MakessurethattheInputStreamisclosedaftertheappis
  24. //finishedusingit.
  25. }finally{
  26. if(stream!=null){
  27. stream.close();
  28. }
  29. }
  30. //StackOverflowXmlParserreturnsaList(called"entries")ofEntryobjects.
  31. //EachEntryobjectrepresentsasinglepostintheXMLfeed.
  32. //ThissectionprocessestheentrieslisttocombineeachentrywithHTMLmarkup.
  33. //EachentryisdisplayedintheUIasalinkthatoptionallyincludes
  34. //atextsummary.
  35. for(Entryentry:entries){
  36. htmlString.append("<p><ahref='");
  37. htmlString.append(entry.link);
  38. htmlString.append("'>"+entry.title+"</a></p>");
  39. //Iftheusersetthepreferencetoincludesummarytext,
  40. //addsittothedisplay.
  41. if(pref){
  42. htmlString.append(entry.summary);
  43. }
  44. }
  45. returnhtmlString.toString();
  46. }
  47. //GivenastringrepresentationofaURL,setsupaconnectionandgets
  48. //aninputstream.
  49. privateInputStreamdownloadUrl(StringurlString)throwsIOException{
  50. URLurl=newURL(urlString);
  51. HttpURLConnectionconn=(HttpURLConnection)url.openConnection();
  52. conn.setReadTimeout(10000/*milliseconds*/);
  53. conn.setConnectTimeout(15000/*milliseconds*/);
  54. conn.setRequestMethod("GET");
  55. conn.setDoInput(true);
  56. //Startsthequery
  57. conn.connect();
  58. InputStreamstream=conn.getInputStream();
  59. }

上面的片段代码为了帮助大家理解,这里还是老习惯,贴上项目的源代码,本来是有项目截图,运行效果图之类的图的,只是这篇文章太长了,再弄图片,就更占篇幅了,所以就只贴源码了,大家可以自己的运行起来看看,希望能从整体的架构和具体的代码细节上帮助到大家。

本篇我们会介绍连接到网络中涉及的基本任务,监测的网络连接(包括连接更改),并给予用户控制应用程序的网络使用情况。还介绍了如何解析和使用XML数据。

这个类包含一个示例应用程序来说明如何执行常见的网络操作。您可以下载示例(在右边),并用它作为自己的应用程序源代码的可重用代码。本章的重点有三:

1.连接到网络

2.管理网络的使用

3.解析XML数据

一、连接到网络

在mainfest中声明权限,代码如下:

Java代码
  1. <uses-permissionandroid:name="android.permission.INTERNET"/>
  2. <uses-permissionandroid:name="android.permission.ACCESS_NETWORK_STATE"/>

选择http客户端

大多数联网的Android应用程序使用HTTP来发送和接收数据。Android包括两个HTTP客户:HttpURLConnection HttpClient和Apache。都支持HTTPS,流媒体上传和下载,可配置的超时,IPv6,和连接池。我们建议使用HttpURLConnection目标应用程序。

检查网络连接

在你的应用程序尝试连接到网络,它应该检查是否一个网络连接可用使用getActiveNetworkInfo()和一个()。记住,这个装置可能范围的一个网络,或用户可能已经禁用wi - fi和移动数据访问。

Java代码
  1. publicvoidmyClickHandler(Viewview){
  2. ...
  3. ConnectivityManagerconnMgr=(ConnectivityManager)
  4. getSystemService(Context.CONNECTIVITY_SERVICE);
  5. NetworkInfonetworkInfo=connMgr.getActiveNetworkInfo();
  6. if(networkInfo!=null&&networkInfo.isConnected()){
  7. //fetchdata
  8. }else{
  9. //displayerror
  10. }
  11. ...
  12. }

在单独线程中执行网络操作

网络操作可以包括不可预测的延迟。为了防止这种导致一个糟糕的用户体验,总是执行网络操作在一个单独的线程。

Java代码
  1. publicclassHttpExampleActivityextendsActivity{
  2. privatestaticfinalStringDEBUG_TAG="HttpExample";
  3. privateEditTexturlText;
  4. privateTextViewtextView;
  5. @Override
  6. publicvoidonCreate(BundlesavedInstanceState){
  7. super.onCreate(savedInstanceState);
  8. setContentView(R.layout.main);
  9. urlText=(EditText)findViewById(R.id.myUrl);
  10. textView=(TextView)findViewById(R.id.myText);
  11. }
  12. //Whenuserclicksbutton,callsAsyncTask.
  13. //BeforeattemptingtofetchtheURL,makessurethatthereisanetworkconnection.
  14. publicvoidmyClickHandler(Viewview){
  15. //GetstheURLfromtheUI'stextfield.
  16. StringstringUrl=urlText.getText().toString();
  17. ConnectivityManagerconnMgr=(ConnectivityManager)
  18. getSystemService(Context.CONNECTIVITY_SERVICE);
  19. NetworkInfonetworkInfo=connMgr.getActiveNetworkInfo();
  20. if(networkInfo!=null&&networkInfo.isConnected()){
  21. newDownloadWebpageText().execute(stringUrl);
  22. }else{
  23. textView.setText("Nonetworkconnectionavailable.");
  24. }
  25. }
  26. //UsesAsyncTasktocreateataskawayfromthemainUIthread.Thistasktakesa
  27. //URLstringandusesittocreateanHttpUrlConnection.Oncetheconnection
  28. //hasbeenestablished,theAsyncTaskdownloadsthecontentsofthewebpageas
  29. //anInputStream.Finally,theInputStreamisconvertedintoastring,whichis
  30. //displayedintheUIbytheAsyncTask'sonPostExecutemethod.
  31. privateclassDownloadWebpageTextextendsAsyncTask{
  32. @Override
  33. protectedStringdoInBackground(String...urls){
  34. //paramscomesfromtheexecute()call:params[0]istheurl.
  35. try{
  36. returndownloadUrl(urls[0]);
  37. }catch(IOExceptione){
  38. return"Unabletoretrievewebpage.URLmaybeinvalid.";
  39. }
  40. }
  41. //onPostExecutedisplaystheresultsoftheAsyncTask.
  42. @Override
  43. protectedvoidonPostExecute(Stringresult){
  44. textView.setText(result);
  45. }
  46. }
  47. ...
  48. }

连接和下载数据

在你的线程执行您的网络交易,你可以使用HttpURLConnection来执行一个GET和下载数据。在您调用connect(),你可以得到一个InputStream的数据通过调用getInputStream()。

Java代码
  1. //GivenaURL,establishesanHttpUrlConnectionandretrieves
  2. //thewebpagecontentasaInputStream,whichitreturnsas
  3. //astring.
  4. privateStringdownloadUrl(Stringmyurl)throwsIOException{
  5. InputStreamis=null;
  6. //Onlydisplaythefirst500charactersoftheretrieved
  7. //webpagecontent.
  8. intlen=500;
  9. try{
  10. URLurl=newURL(myurl);
  11. HttpURLConnectionconn=(HttpURLConnection)url.openConnection();
  12. conn.setReadTimeout(10000/*milliseconds*/);
  13. conn.setConnectTimeout(15000/*milliseconds*/);
  14. conn.setRequestMethod("GET");
  15. conn.setDoInput(true);
  16. //Startsthequery
  17. conn.connect();
  18. intresponse=conn.getResponseCode();
  19. Log.d(DEBUG_TAG,"Theresponseis:"+response);
  20. is=conn.getInputStream();
  21. //ConverttheInputStreamintoastring
  22. StringcontentAsString=readIt(is,len);
  23. returncontentAsString;
  24. //MakessurethattheInputStreamisclosedaftertheappis
  25. //finishedusingit.
  26. }finally{
  27. if(is!=null){
  28. is.close();
  29. }
  30. }
  31. }

getResponseCode()返回连接的状态码。这是一种有用的方式获得一些额外的信息的连接。一个200的状态代码表示成功。

转换InputStreamString

Java代码
  1. //ReadsanInputStreamandconvertsittoaString.
  2. publicStringreadIt(InputStreamstream,intlen)throwsIOException,UnsupportedEncodingException{
  3. Readerreader=null;
  4. reader=newInputStreamReader(stream,"UTF-8");
  5. char[]buffer=newchar[len];
  6. reader.read(buffer);
  7. returnnewString(buffer);
  8. }

二、管理网络

检查设备的网络连接

一个设备可以有各种类型的网络连接。这节课的重点是使用wi - fi或手机或网络连接,这个代码片段测试网络连接wi - fi和移动。它确定这些网络接口是可用的或连接的(即网络连接是否存在,如果可以建立套接字和传递数据)

Java代码
  1. privatestaticfinalStringDEBUG_TAG="NetworkStatusExample";
  2. ...
  3. ConnectivityManagerconnMgr=(ConnectivityManager)
  4. getSystemService(Context.CONNECTIVITY_SERVICE);
  5. NetworkInfonetworkInfo=connMgr.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
  6. booleanisWifiConn=networkInfo.isConnected();
  7. networkInfo=connMgr.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
  8. booleanisMobileConn=networkInfo.isConnected();
  9. Log.d(DEBUG_TAG,"Wificonnected:"+isWifiConn);
  10. Log.d(DEBUG_TAG,"Mobileconnected:"+isMobileConn);

管理网络的使用

您可以实现一个首选项活动,让用户明确控制应用程序的使用网络资源。例如:1.你可能允许用户上传的视频只有当设备被连接到wi - fi网络。2.你可能会同步(或没有)根据特定标准如网络可用性、时间间隔,等等。

编写一个应用程序,支持网络访问和管理网络的使用,你的清单必须有正确的权限和意图过滤器。

在样例应用程序中,这个规定了SettingsActivity,将显示一个UI让用户知道何时可以进行下载操作。

Xml代码
  1. <?xmlversion="1.0"encoding="utf-8"?>
  2. <manifestxmlns:android="http://schemas.android.com/apk/res/android"
  3. package="com.example.android.networkusage"
  4. ...>
  5. <uses-sdkandroid:minSdkVersion="4"
  6. android:targetSdkVersion="14"/>
  7. <uses-permissionandroid:name="android.permission.INTERNET"/>
  8. <uses-permissionandroid:name="android.permission.ACCESS_NETWORK_STATE"/>
  9. <application
  10. ...>
  11. ...
  12. <activityandroid:label="SettingsActivity"android:name=".SettingsActivity">
  13. <intent-filter>
  14. <actionandroid:name="android.intent.action.MANAGE_NETWORK_USAGE"/>
  15. <categoryandroid:name="android.intent.category.DEFAULT"/>
  16. </intent-filter>
  17. </activity>
  18. </application>
  19. </manifest>

Java代码
  1. publicclassSettingsActivityextendsPreferenceActivityimplementsOnSharedPreferenceChangeListener{
  2. @Override
  3. protectedvoidonCreate(BundlesavedInstanceState){
  4. super.onCreate(savedInstanceState);
  5. //LoadstheXMLpreferencesfile
  6. addPreferencesFromResource(R.xml.preferences);
  7. }
  8. @Override
  9. protectedvoidonResume(){
  10. super.onResume();
  11. //Registersalistenerwheneverakeychanges
  12. getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
  13. }
  14. @Override
  15. protectedvoidonPause(){
  16. super.onPause();
  17. //UnregistersthelistenersetinonResume().
  18. //It'sbestpracticetounregisterlistenerswhenyourappisn'tusingthemtocutdownon
  19. //unnecessarysystemoverhead.YoudothisinonPause().
  20. getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
  21. }
  22. //Whentheuserchangesthepreferencesselection,
  23. //onSharedPreferenceChanged()restartsthemainactivityasanew
  24. //task.SetsthetherefreshDisplayflagto"true"toindicatethat
  25. //themainactivityshouldupdateitsdisplay.
  26. //ThemainactivityqueriesthePreferenceManagertogetthelatestsettings.
  27. @Override
  28. publicvoidonSharedPreferenceChanged(SharedPreferencessharedPreferences,Stringkey){
  29. //SetsrefreshDisplaytotruesothatwhentheuserreturnstothemain
  30. //activity,thedisplayrefreshestoreflectthenewsettings.
  31. NetworkActivity.refreshDisplay=true;
  32. }
  33. }

响应网络变动

如果有一个匹配发生在设置和设备的网络连接(例如,如果设置为“wi - fi”和设备有一个wi - fi连接)之间,应用程序下载提继续并刷新显示

Java代码
  1. publicclassNetworkActivityextendsActivity{
  2. publicstaticfinalStringWIFI="Wi-Fi";
  3. publicstaticfinalStringANY="Any";
  4. privatestaticfinalStringURL="http://stackoverflow.com/feeds/tag?tagnames=android&sort=newest";
  5. //WhetherthereisaWi-Ficonnection.
  6. privatestaticbooleanwifiConnected=false;
  7. //Whetherthereisamobileconnection.
  8. privatestaticbooleanmobileConnected=false;
  9. //Whetherthedisplayshouldberefreshed.
  10. publicstaticbooleanrefreshDisplay=true;
  11. //Theuser'scurrentnetworkpreferencesetting.
  12. publicstaticStringsPref=null;
  13. //TheBroadcastReceiverthattracksnetworkconnectivitychanges.
  14. privateNetworkReceiverreceiver=newNetworkReceiver();
  15. @Override
  16. publicvoidonCreate(BundlesavedInstanceState){
  17. super.onCreate(savedInstanceState);
  18. //RegistersBroadcastReceivertotracknetworkconnectionchanges.
  19. IntentFilterfilter=newIntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
  20. receiver=newNetworkReceiver();
  21. this.registerReceiver(receiver,filter);
  22. }
  23. @Override
  24. publicvoidonDestroy(){
  25. super.onDestroy();
  26. //UnregistersBroadcastReceiverwhenappisdestroyed.
  27. if(receiver!=null){
  28. this.unregisterReceiver(receiver);
  29. }
  30. }
  31. //Refreshesthedisplayifthenetworkconnectionandthe
  32. //prefsettingsallowit.
  33. @Override
  34. publicvoidonStart(){
  35. super.onStart();
  36. //Getstheuser'snetworkpreferencesettings
  37. SharedPreferencessharedPrefs=PreferenceManager.getDefaultSharedPreferences(this);
  38. //Retrievesastringvalueforthepreferences.Thesecondparameter
  39. //isthedefaultvaluetouseifapreferencevalueisnotfound.
  40. sPref=sharedPrefs.getString("listPref","Wi-Fi");
  41. updateConnectedFlags();
  42. if(refreshDisplay){
  43. loadPage();
  44. }
  45. }
  46. //ChecksthenetworkconnectionandsetsthewifiConnectedandmobileConnected
  47. //variablesaccordingly.
  48. publicvoidupdateConnectedFlags(){
  49. ConnectivityManagerconnMgr=(ConnectivityManager)
  50. getSystemService(Context.CONNECTIVITY_SERVICE);
  51. NetworkInfoactiveInfo=connMgr.getActiveNetworkInfo();
  52. if(activeInfo!=null&&activeInfo.isConnected()){
  53. wifiConnected=activeInfo.getType()==ConnectivityManager.TYPE_WIFI;
  54. mobileConnected=activeInfo.getType()==ConnectivityManager.TYPE_MOBILE;
  55. }else{
  56. wifiConnected=false;
  57. mobileConnected=false;
  58. }
  59. }
  60. //UsesAsyncTasksubclasstodownloadtheXMLfeedfromstackoverflow.com.
  61. publicvoidloadPage(){
  62. if(((sPref.equals(ANY))&&(wifiConnected||mobileConnected))
  63. ||((sPref.equals(WIFI))&&(wifiConnected))){
  64. //AsyncTasksubclass
  65. newDownloadXmlTask().execute(URL);
  66. }else{
  67. showErrorPage();
  68. }
  69. }
  70. ...
  71. }

检测网络连接变化

Java代码
  1. publicclassNetworkReceiverextendsBroadcastReceiver{
  2. @Override
  3. publicvoidonReceive(Contextcontext,Intentintent){
  4. ConnectivityManagerconn=(ConnectivityManager)
  5. context.getSystemService(Context.CONNECTIVITY_SERVICE);
  6. NetworkInfonetworkInfo=conn.getActiveNetworkInfo();
  7. //Checkstheuserprefsandthenetworkconnection.Basedontheresult,decideswhether
  8. //torefreshthedisplayorkeepthecurrentdisplay.
  9. //IftheuserprefisWi-Fionly,checkstoseeifthedevicehasaWi-Ficonnection.
  10. if(WIFI.equals(sPref)&&networkInfo!=null&&networkInfo.getType()==ConnectivityManager.TYPE_WIFI){
  11. //IfdevicehasitsWi-Ficonnection,setsrefreshDisplay
  12. //totrue.Thiscausesthedisplaytoberefreshedwhentheuser
  13. //returnstotheapp.
  14. refreshDisplay=true;
  15. Toast.makeText(context,R.string.wifi_connected,Toast.LENGTH_SHORT).show();
  16. //IfthesettingisANYnetworkandthereisanetworkconnection
  17. //(whichbyprocessofeliminationwouldbemobile),setsrefreshDisplaytotrue.
  18. }elseif(ANY.equals(sPref)&&networkInfo!=null){
  19. refreshDisplay=true;
  20. //Otherwise,theappcan'tdownloadcontent--eitherbecausethereisnonetwork
  21. //connection(mobileorWi-Fi),orbecausetheprefsettingisWIFI,andthere
  22. //isnoWi-Ficonnection.
  23. //SetsrefreshDisplaytofalse.
  24. }else{
  25. refreshDisplay=false;
  26. Toast.makeText(context,R.string.lost_connection,Toast.LENGTH_SHORT).show();
  27. }
  28. }

三、解析xml

上传和解析XML数据是很常见的任务,网络连接应用程序。这一课解释了如何解析XML文档并使用他们的数据

选择转换器

我们建议XmlPullParser,这是一种高效且可维护的方式来解析XML在Android里。

分析需求

Xml代码
  1. <?xmlversion="1.0"encoding="utf-8"?>
  2. <feedxmlns="http://www.w3.org/2005/Atom"xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule"...">
  3. <titletype="text">newestquestionstaggedandroid-StackOverflow</title>
  4. ...
  5. <entry>
  6. ...
  7. </entry>
  8. <entry>
  9. <id>http://stackoverflow.com/q/9439999</id>
  10. <re:rankscheme="http://stackoverflow.com">0</re:rank>
  11. <titletype="text">Whereismydatafile?</title>
  12. <categoryscheme="http://stackoverflow.com/feeds/tag?tagnames=android&sort=newest/tags"term="android"/>
  13. <categoryscheme="http://stackoverflow.com/feeds/tag?tagnames=android&sort=newest/tags"term="file"/>
  14. <author>
  15. <name>cliff2310</name>
  16. <uri>http://stackoverflow.com/users/1128925</uri>
  17. </author>
  18. <linkrel="alternate"href="http://stackoverflow.com/questions/9439999/where-is-my-data-file"/>
  19. <published>2012-02-25T00:30:54Z</published>
  20. <updated>2012-02-25T00:30:54Z</updated>
  21. <summarytype="html">
  22. <p>IhaveanApplicationthatrequiresadatafile...</p>
  23. </summary>
  24. </entry>
  25. <entry>
  26. ...
  27. </entry>
  28. ...
  29. </feed>

实例化转化器

Java代码
  1. publicclassStackOverflowXmlParser{
  2. //Wedon'tusenamespaces
  3. privatestaticfinalStringns=null;
  4. publicListparse(InputStreamin)throwsXmlPullParserException,IOException{
  5. try{
  6. XmlPullParserparser=Xml.newPullParser();
  7. parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES,false);
  8. parser.setInput(in,null);
  9. parser.nextTag();
  10. returnreadFeed(parser);
  11. }finally{
  12. in.close();
  13. }
  14. }
  15. ...
  16. }
  17. 读取xml
  18. privateListreadFeed(XmlPullParserparser)throwsXmlPullParserException,IOException{
  19. Listentries=newArrayList();
  20. parser.require(XmlPullParser.START_TAG,ns,"feed");
  21. while(parser.next()!=XmlPullParser.END_TAG){
  22. if(parser.getEventType()!=XmlPullParser.START_TAG){
  23. continue;
  24. }
  25. Stringname=parser.getName();
  26. //Startsbylookingfortheentrytag
  27. if(name.equals("entry")){
  28. entries.add(readEntry(parser));
  29. }else{
  30. skip(parser);
  31. }
  32. }
  33. returnentries;
  34. }

下面这个代码片段展示了如何解析器解析条目、标题、链接和总结:

Java代码
  1. publicstaticclassEntry{
  2. publicfinalStringtitle;
  3. publicfinalStringlink;
  4. publicfinalStringsummary;
  5. privateEntry(Stringtitle,Stringsummary,Stringlink){
  6. this.title=title;
  7. this.summary=summary;
  8. this.link=link;
  9. }
  10. }
  11. //Parsesthecontentsofanentry.Ifitencountersatitle,summary,orlinktag,handsthemoff
  12. //totheirrespective"read"methodsforprocessing.Otherwise,skipsthetag.
  13. privateEntryreadEntry(XmlPullParserparser)throwsXmlPullParserException,IOException{
  14. parser.require(XmlPullParser.START_TAG,ns,"entry");
  15. Stringtitle=null;
  16. Stringsummary=null;
  17. Stringlink=null;
  18. while(parser.next()!=XmlPullParser.END_TAG){
  19. if(parser.getEventType()!=XmlPullParser.START_TAG){
  20. continue;
  21. }
  22. Stringname=parser.getName();
  23. if(name.equals("title")){
  24. title=readTitle(parser);
  25. }elseif(name.equals("summary")){
  26. summary=readSummary(parser);
  27. }elseif(name.equals("link")){
  28. link=readLink(parser);
  29. }else{
  30. skip(parser);
  31. }
  32. }
  33. returnnewEntry(title,summary,link);
  34. }
  35. //Processestitletagsinthefeed.
  36. privateStringreadTitle(XmlPullParserparser)throwsIOException,XmlPullParserException{
  37. parser.require(XmlPullParser.START_TAG,ns,"title");
  38. Stringtitle=readText(parser);
  39. parser.require(XmlPullParser.END_TAG,ns,"title");
  40. returntitle;
  41. }
  42. //Processeslinktagsinthefeed.
  43. privateStringreadLink(XmlPullParserparser)throwsIOException,XmlPullParserException{
  44. Stringlink="";
  45. parser.require(XmlPullParser.START_TAG,ns,"link");
  46. Stringtag=parser.getName();
  47. StringrelType=parser.getAttributeValue(null,"rel");
  48. if(tag.equals("link")){
  49. if(relType.equals("alternate")){
  50. link=parser.getAttributeValue(null,"href");
  51. parser.nextTag();
  52. }
  53. }
  54. parser.require(XmlPullParser.END_TAG,ns,"link");
  55. returnlink;
  56. }
  57. //Processessummarytagsinthefeed.
  58. privateStringreadSummary(XmlPullParserparser)throwsIOException,XmlPullParserException{
  59. parser.require(XmlPullParser.START_TAG,ns,"summary");
  60. Stringsummary=readText(parser);
  61. parser.require(XmlPullParser.END_TAG,ns,"summary");
  62. returnsummary;
  63. }
  64. //Forthetagstitleandsummary,extractstheirtextvalues.
  65. privateStringreadText(XmlPullParserparser)throwsIOException,XmlPullParserException{
  66. Stringresult="";
  67. if(parser.next()==XmlPullParser.TEXT){
  68. result=parser.getText();
  69. parser.nextTag();
  70. }
  71. returnresult;
  72. }
  73. ...
  74. }

跳过无用的标签

Java代码
  1. privatevoidskip(XmlPullParserparser)throwsXmlPullParserException,IOException{
  2. if(parser.getEventType()!=XmlPullParser.START_TAG){
  3. thrownewIllegalStateException();
  4. }
  5. intdepth=1;
  6. while(depth!=0){
  7. switch(parser.next()){
  8. caseXmlPullParser.END_TAG:
  9. depth--;
  10. break;
  11. caseXmlPullParser.START_TAG:
  12. depth++;
  13. break;
  14. }
  15. }
  16. }

使用xml数据

Java代码
  1. publicclassNetworkActivityextendsActivity{
  2. publicstaticfinalStringWIFI="Wi-Fi";
  3. publicstaticfinalStringANY="Any";
  4. privatestaticfinalStringURL="http://stackoverflow.com/feeds/tag?tagnames=android&sort=newest";
  5. //WhetherthereisaWi-Ficonnection.
  6. privatestaticbooleanwifiConnected=false;
  7. //Whetherthereisamobileconnection.
  8. privatestaticbooleanmobileConnected=false;
  9. //Whetherthedisplayshouldberefreshed.
  10. publicstaticbooleanrefreshDisplay=true;
  11. publicstaticStringsPref=null;
  12. ...
  13. //UsesAsyncTasktodownloadtheXMLfeedfromstackoverflow.com.
  14. publicvoidloadPage(){
  15. if((sPref.equals(ANY))&&(wifiConnected||mobileConnected)){
  16. newDownloadXmlTask().execute(URL);
  17. }
  18. elseif((sPref.equals(WIFI))&&(wifiConnected)){
  19. newDownloadXmlTask().execute(URL);
  20. }else{
  21. //showerror
  22. }
  23. }

动态下载xml

Java代码
  1. //ImplementationofAsyncTaskusedtodownloadXMLfeedfromstackoverflow.com.
  2. privateclassDownloadXmlTaskextendsAsyncTask<String,Void,String>{
  3. @Override
  4. protectedStringdoInBackground(String...urls){
  5. try{
  6. returnloadXmlFromNetwork(urls[0]);
  7. }catch(IOExceptione){
  8. returngetResources().getString(R.string.connection_error);
  9. }catch(XmlPullParserExceptione){
  10. returngetResources().getString(R.string.xml_error);
  11. }
  12. }
  13. @Override
  14. protectedvoidonPostExecute(Stringresult){
  15. setContentView(R.layout.main);
  16. //DisplaystheHTMLstringintheUIviaaWebView
  17. WebViewmyWebView=(WebView)findViewById(R.id.webview);
  18. myWebView.loadData(result,"text/html",null);
  19. }
  20. }

加载xml

Java代码
  1. //UploadsXMLfromstackoverflow.com,parsesit,andcombinesitwith
  2. //HTMLmarkup.ReturnsHTMLstring.
  3. privateStringloadXmlFromNetwork(StringurlString)throwsXmlPullParserException,IOException{
  4. InputStreamstream=null;
  5. //Instantiatetheparser
  6. StackOverflowXmlParserstackOverflowXmlParser=newStackOverflowXmlParser();
  7. List<Entry>entries=null;
  8. Stringtitle=null;
  9. Stringurl=null;
  10. Stringsummary=null;
  11. CalendarrightNow=Calendar.getInstance();
  12. DateFormatformatter=newSimpleDateFormat("MMMddh:mmaa");
  13. //Checkswhethertheusersetthepreferencetoincludesummarytext
  14. SharedPreferencessharedPrefs=PreferenceManager.getDefaultSharedPreferences(this);
  15. booleanpref=sharedPrefs.getBoolean("summaryPref",false);
  16. StringBuilderhtmlString=newStringBuilder();
  17. htmlString.append("<h3>"+getResources().getString(R.string.page_title)+"</h3>");
  18. htmlString.append("<em>"+getResources().getString(R.string.updated)+""+
  19. formatter.format(rightNow.getTime())+"</em>");
  20. try{
  21. stream=downloadUrl(urlString);
  22. entries=stackOverflowXmlParser.parse(stream);
  23. //MakessurethattheInputStreamisclosedaftertheappis
  24. //finishedusingit.
  25. }finally{
  26. if(stream!=null){
  27. stream.close();
  28. }
  29. }
  30. //StackOverflowXmlParserreturnsaList(called"entries")ofEntryobjects.
  31. //EachEntryobjectrepresentsasinglepostintheXMLfeed.
  32. //ThissectionprocessestheentrieslisttocombineeachentrywithHTMLmarkup.
  33. //EachentryisdisplayedintheUIasalinkthatoptionallyincludes
  34. //atextsummary.
  35. for(Entryentry:entries){
  36. htmlString.append("<p><ahref='");
  37. htmlString.append(entry.link);
  38. htmlString.append("'>"+entry.title+"</a></p>");
  39. //Iftheusersetthepreferencethttp://oincludesummarytext,
  40. //addsittothedisplay.
  41. if(pref){
  42. htmlString.append(entry.summary);
  43. }
  44. }
  45. returnhtmlString.toString();
  46. }
  47. //GivenastringrepresentationofaURL,setsupaconnectionandgets
  48. //aninputstream.
  49. privateInputStreamdownloadUrl(StringurlString)throwsIOException{
  50. URLurl=newURL(urlString);
  51. HttpURLConnectionconn=(HttpURLConnection)url.openConnection();
  52. conn.setReadTimeout(10000/*milliseconds*/);
  53. conn.setConnectTimeout(15000/*milliseconds*/);
  54. conn.setRequestMethod("GET");
  55. conn.setDoInput(true);
  56. //Startsthequery
  57. conn.connect();
  58. InputStreamstream=conn.getInputStream();
  59. }

上面的片段代码为了帮助大家理解,这里还是老习惯,贴上项目的源代码,本来是有项目截图,运行效果图之类的图的,只是这篇文章太长了,再弄图片,就更占篇幅了,所以就只贴源码了,大家可以自己的运行起来看看,希望能从整体的架构和具体的代码细节上帮助到大家。点击打开下载链接

分享到:
评论

相关推荐

    android网络操作

    在Android平台上进行网络操作是应用程序开发中的重要环节,它允许应用与远程服务器进行数据交互,如获取用户信息、上传下载文件、同步数据等。本文将深入探讨“Android网络操作”的核心概念、常用方法以及如何利用...

    Android耗时操作Demo

    Android应用的主要交互发生在主线程,如果在这个线程执行耗时操作(如网络请求、数据库操作或大文件读写),会导致UI无响应,即著名的ANR(Application Not Responding)错误。为了解决这个问题,Android提供了线程...

    android 执行系统命令

    如果需要执行网络相关的命令,则需要: ```xml &lt;uses-permission android:name="android.permission.INTERNET"/&gt; ``` 更复杂的情况下,可能需要动态请求权限,特别是在Android 6.0(API级别23)及以上版本。 对于...

    如何让Android系统或Android应用执行shell脚本

    Android 系统或 Android 应用执行 shell 脚本是 Android 开发中的一项重要技术,通过执行 shell 脚本,可以实现一些复杂的操作,例如设置网络参数、启动服务等。下面我们将介绍两种让 Android 系统或 Android 应用...

    Android 网络类型及操作相关demo

    在Android开发中,网络操作是不可或缺的一部分,尤其是在构建与服务器交互的应用时。本Demo——"Android 网络类型及操作相关demo"专注于检测和管理设备的网络状态,特别是WiFi和移动数据。以下是对该Demo中涉及的...

    android 网络操作 封装 直接调用

    在Android开发中,网络操作是不可或缺的一部分,它使得应用程序能够获取远程数据,实现与服务器的交互。本知识点主要聚焦于如何在Android中进行网络操作的封装,以便开发者能更便捷地进行网络请求,提高开发效率。 ...

    android网络开发原理

    此外,Android有严格的网络访问策略,比如在主线程中直接进行网络操作会导致ANR(Application Not Responding)错误,因此网络操作通常应在工作线程或者IntentService中执行。为了提高用户体验,还可以使用AsyncTask...

    线程实现的Android访问网络资源

    在Android 4.0及以上版本中,为了保证用户界面的流畅性,网络操作通常不会在主线程中执行,而是通过子线程或者异步任务来处理。以下是对这个主题的详细阐述: 1. **网络访问基础** - Android系统出于性能和用户...

    android实战 网络图片浏览器(android studio源程序工程)

    由于Android主线程不支持耗时操作,网络请求和图片加载通常在后台线程执行,然后通过Handler、AsyncTask或者使用RxJava等异步编程库来更新UI。 总的来说,这个“android实战 网络图片浏览器”项目涵盖了Android开发...

    android访问网络例程

    4. **网络请求的异步处理**:Android主线程不应直接执行网络操作,否则可能导致应用无响应。可以使用AsyncTask、Handler/Looper或Retrofit(一个基于OkHttp的高级网络库)进行异步处理。 5. **HTTPS与安全**:对于...

    android从网络获取图片资源,图片放大、缩小、触摸等操作。

    你可以创建一个继承自AsyncTask的类,重写doInBackground()方法来执行网络请求,然后在onPostExecute()方法中更新UI。 2. **使用Volley库**:Volley是Google推荐的网络请求库,它内部实现了线程池和请求队列,能...

    Android 网络调试助手

    2. 运行应用:启动待调试的应用,执行网络操作。 3. 监控调试:在调试助手中查看捕获的网络请求,分析问题。 4. 修改与重发:若需要,可修改请求参数并重新发送,观察不同参数下的服务器响应。 5. 结束调试:完成...

    Android操作系统概述

    系统运行库层是Android的核心组成部分,它包含了各种库和运行环境,如Dalvik虚拟机(现在已被ART取代)用于执行Java代码,以及C/C++库,如SQLite用于数据库管理,OpenSSL用于网络安全,以及多媒体框架等。...

    android 文件、网络、数据库、UI基本操作总结

    在Android开发中,掌握文件操作、网络通信、数据库管理和用户界面(UI)设计是至关重要的。以下是对这些关键知识点的详细说明: 1. **文件操作**: - Android中的文件操作主要包括读取和写入。`File`类是进行文件...

    【Android】Android 监听网络状态+源代码

    // 网络连接可用,执行网络操作 } else { // 网络未连接,提示用户或执行相应操作 } ``` 5. **监听网络变化** 若要实时监听网络状态的变化,可以注册一个`BroadcastReceiver`来接收网络状态改变的广播: ```...

    android检测网络两个方法

    罗列了android常用两种检测网络方法,在工作线程中定时执行检测操作

    精通android网络开发

    3. **AsyncTask**:Android提供的轻量级异步任务类,用于在后台线程执行网络操作,避免阻塞UI线程。但因为生命周期问题,不建议在大型项目中广泛使用。 4. **Volley库**:Google推出的网络请求库,提供了高效的缓存...

    android 检测网络状态

    这不仅可以帮助开发者判断应用程序是否应该执行某些依赖于网络的操作(例如数据同步、下载资源等),还可以根据当前网络环境为用户提供更合适的提示或界面显示。 #### 1. 导入必要的包 首先,为了实现检测网络状态...

Global site tag (gtag.js) - Google Analytics