码迷,mamicode.com
首页 > 移动开发 > 详细

6、android 网络编程

时间:2015-07-07 00:47:02      阅读:497      评论:0      收藏:0      [点我收藏+]

标签:

1基于socket的用法

  服务器端:

  先启动一个服务器端的socket     ServerSocket svr = new ServerSocket(8989);

  开始侦听请求         Socket s = svr.accept();

  取得输入和输出        DataInputStream dis = new DataInputStream(s.getInputStream());

                 DataOutputStream dos = new DataOutputStream(s.getOutputStream());

  Socket 的交互通过流来完成,即是说传送的字节流,因此任何文件都可以在上面传送。谁打开的记得要关上。

  用DataInputStream/DataOutputStream来进行包装是因为我们想要他们对基本数据类型的读写功能readInt(),writeInt(),readUTF(),writeUTF()等等。

  客户端:

  发起一个socket连接      Socket s = new Socket("192.168.1.200",8989);

  取得输入和输出        DataInputStream dis = new DataInputStream(s.getInputStream());

                 DataOutputStream dos = new DataOutputStream(s.getOutputStream());

  之后就可以相互通信了。谁打开的记得要关上。

2基于Http协议

  一般是发送请求到某个应用服务器。此时需要用到HttpURLConnection

  先取得HttpURLConnection urlConn = new URL("http://www.google.com").openConnection();

  设置标志 

    urlConn.setDoOutput(true);  urlConn.setDoInput(true);//post的情况下需要设置DoOutputtrue

    urlConn.setRequestMethod("POST");

    urlConn.setUseCache(false);//设置是否用缓存

    urlConn.setRequestProperty("Content-type","application/x-www-form-urlencoded");//设置contenttype

  获得输出流,便于想服务器发送信息。

    DataOutputStream dos = new DataOutputStream(urlConn.getOutputStream());

  望流里面写请求参数

    dos.writeBytes("name="+URLEncoder.encode("chenmouren","gb2312");

    dos.flush();dos.close();//发送完后马上关闭。

  获得输入流,取数据

    BufferReader reader = new BufferedReader(new InputStreamReader(urlConn.getInputStream()));

    reader.readLine();//用 !=null来判断是否结束

    reader.close();

  读完了记得关闭connection  urlConn.disconnect();

流程记录就到此为止。

3、HttpURLConnection接口
    首先需要明确的是,Http通信中的POST和GET请求方式的不同。GET可以获得静态页面,也可以把参数放在URL字符串后面,传递给服务器。而POST方法的参数是放在Http请求中。因此,在编程之前,应当首先明确使用的请求方法,然后再根据所使用的方式选择相应的编程方式。
    HttpURLConnection是继承于URLConnection类,二者都是抽象类。其对象主要通过URL的openConnection方法获得。创建方法如下代码所示:

 
 

  1. URL url = new URL("http://www.51cto.com/index.jsp?par=123456");  
  2. HttpURLConnection urlConn=(HttpURLConnection)url.openConnection(); 

   

    通过以下方法可以对请求的属性进行一些设置,如下所示:

 
 

  1. //设置输入和输出流  
  2. urlConn.setDoOutput(true);  
  3. urlConn.setDoInput(true);  
  4. //设置请求方式为POST  
  5. urlConn.setRequestMethod("POST");  
  6. //POST请求不能使用缓存  
  7. urlConn.setUseCaches(false);  
  8. //关闭连接  
  9. urlConn.disConnection();  



HttpURLConnection默认使用GET方式,例如下面代码所示:

 
 

  1. //使用HttpURLConnection打开连接  
  2. HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();  
  3. //得到读取的内容( 
  4. InputStreamReader in = new InputStreamReader(urlConn.getInputStream());  
  5. // 为输出创建BufferedReader  
  6. BufferedReader buffer = new BufferedReader(in);  
  7. String inputLine = null;  
  8. //使用循环来读取获得的数据  
  9. while (((inputLine = buffer.readLine()) != null))  
  10. {  
  11. //我们在每一行后面加上一个"\n"来换行  
  12. resultData += inputLine + "\n";  
  13. }           
  14. //关闭InputStreamReader  
  15. in.close();  
  16. //关闭http连接  
  17. urlConn.disconnect(); 



    如果需要使用POST方式,则需要setRequestMethod设置。代码如下:

 
 

  1. String httpUrl = "http://192.168.1.110:8080/httpget.jsp";  
  2. //获得的数据  
  3. String resultData = "";  
  4. URL url = null;  
  5. try 
  6. {  
  7. //构造一个URL对象  
  8. url = new URL(httpUrl);   
  9. }  
  10. catch (MalformedURLException e)  
  11. {  
  12. Log.e(DEBUG_TAG, "MalformedURLException");  
  13. }  
  14. if (url != null)  
  15. {  
  16. try 
  17. {  
  18. // 使用HttpURLConnection打开连接  
  19. HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();  
  20. //因为这个是post请求,设立需要设置为true  
  21. urlConn.setDoOutput(true);  
  22. urlConn.setDoInput(true);  
  23. // 设置以POST方式  
  24. urlConn.setRequestMethod("POST");  
  25. // Post 请求不能使用缓存  
  26. urlConn.setUseCaches(false);  
  27. urlConn.setInstanceFollowRedirects(true);  
  28. // 配置本次连接的Content-type,配置为application/x-www-form-urlencoded的  
  29. urlConn.setRequestProperty("Content-Type","application/x-www-form-urlencoded");  
  30. // 连接,从postUrl.openConnection()至此的配置必须要在connect之前完成,  
  31. // 要注意的是connection.getOutputStream会隐含的进行connect。  
  32. urlConn.connect();  
  33. //DataOutputStream流  
  34. DataOutputStream out = new DataOutputStream(urlConn.getOutputStream());  
  35. //要上传的参数  
  36. String content = "par=" + URLEncoder.encode("ABCDEFG", "gb2312");  
  37. //将要上传的内容写入流中  
  38. out.writeBytes(content);   
  39. //刷新、关闭  
  40. out.flush();  
  41. out.close();  

 

4、使用Apache提供的HttpClient接口同样可以进行HTTP操作。

    对于GET和POST请求方法的操作有所不同。GET方法的操作代码示例如下:

[java] view plaincopy

  1. // http地址    
  2. String httpUrl = "http://192.168.1.110:8080/httpget.jsp?par=HttpClient_android_Get";    
  3. //HttpGet连接对象    
  4. HttpGet httpRequest = new HttpGet(httpUrl);    
  5. //取得HttpClient对象    
  6. HttpClient httpclient = new DefaultHttpClient();    
  7. //请求HttpClient,取得HttpResponse    
  8. HttpResponse httpResponse = httpclient.execute(httpRequest);    
  9. //请求成功    
  10. if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK)    
  11. {    
  12. //取得返回的字符串    
  13. String strResult = EntityUtils.toString(httpResponse.getEntity());    
  14. mTextView.setText(strResult);    
  15. }    
  16. else   
  17. {    
  18. mTextView.setText("请求错误!");    
  19. }    
  20. }   

 

    使用POST方法进行参数传递时,需要使用NameValuePair来保存要传递的参数。,另外,还需要设置所使用的字符集。代码如下所示:

 

[java] view plaincopy

  1. // http地址    
  2. String httpUrl = "http://192.168.1.110:8080/httpget.jsp";    
  3. //HttpPost连接对象    
  4. HttpPost httpRequest = new HttpPost(httpUrl);    
  5. //使用NameValuePair来保存要传递的Post参数    
  6. List<NameValuePair> params = new ArrayList<NameValuePair>();    
  7. //添加要传递的参数    
  8. params.add(new BasicNameValuePair("par", "HttpClient_android_Post"));    
  9. //设置字符集    
  10. HttpEntity httpentity = new UrlEncodedFormEntity(params, "gb2312");    
  11. //请求httpRequest    
  12. httpRequest.setEntity(httpentity);    
  13. //取得默认的HttpClient    
  14. HttpClient httpclient = new DefaultHttpClient();    
  15. //取得HttpResponse    
  16. HttpResponse httpResponse = httpclient.execute(httpRequest);    
  17. //HttpStatus.SC_OK表示连接成功    
  18. if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK)    
  19. {    
  20. //取得返回的字符串    
  21. String strResult = EntityUtils.toString(httpResponse.getEntity());    
  22. mTextView.setText(strResult);    
  23. }    
  24. else   
  25. {    
  26. mTextView.setText("请求错误!");    
  27. }    
  28. }   

 

HttpClient实际上是对Java提供方法的一些封装,在HttpURLConnection中的输入输出流操作,在这个接口中被统一封装成了HttpPost(HttpGet)和HttpResponse,这样,就减少了操作的繁琐性。

另外,在使用POST方式进行传输时,需要进行字符编码。

5、

  1. package com.study.ws;  
  2. import java.io.IOException;  
  3. import org.ksoap2.SoapEnvelope;  
  4. import org.ksoap2.SoapFault;  
  5. import org.ksoap2.serialization.SoapObject;  
  6. import org.ksoap2.serialization.SoapSerializationEnvelope;  
  7. import org.ksoap2.transport.AndroidHttpTransport;  
  8. import org.ksoap2.transport.HttpTransportSE;  
  9. import org.xmlpull.v1.XmlPullParserException;  
  10. import android.app.Activity;  
  11. import android.os.Bundle;  
  12. import android.view.View;  
  13. import android.view.View.OnClickListener;  
  14. import android.webkit.WebSettings;  
  15. import android.widget.Button;  
  16. import android.widget.EditText;  
  17. import android.widget.TextView;  
  18. public class WSClient extends Activity {  
  19.  private Button search;  
  20.  private EditText phone;  
  21.  private TextView  result;  
  22.     /** Called when the activity is first created. */  
  23.     @Override  
  24.     public void onCreate(Bundle savedInstanceState) {  
  25.         super.onCreate(savedInstanceState);  
  26.         setContentView(R.layout.main);  
  27.         search=(Button)findViewById(R.id.search);  
  28.         phone=(EditText)findViewById(R.id.phone);  
  29.         result=(TextView)findViewById(R.id.result);  
  30.         search.setOnClickListener(new OnClickListener() {  
  31.      
  32.    @Override  
  33.    public void onClick(View v) {  
  34.     String strPhone=phone.getText().toString().trim();  
  35.     if(!(strPhone.length()==0||strPhone.equals("")))  
  36.     {  
  37.       String str = "";  
  38.     try {  
  39.      str = getPhoneInfo(strPhone);  
  40.     } catch (IOException e) {  
  41.      // TODO Auto-generated catch block  
  42.      e.printStackTrace();  
  43.     } catch (XmlPullParserException e) {  
  44.      // TODO Auto-generated catch block  
  45.      e.printStackTrace();  
  46.     }  
  47.       result.setText(str);  
  48.     }  
  49.    }  
  50.   });  
  51.           
  52.     }  
  53.     public String getPhoneInfo(String phoneName) throws IOException, XmlPullParserException  
  54.     {  
  55.      //返回的查询结果  
  56.      String result = null;  
  57.      //调用webservice接口的名称空间  
  58.      String nameSpace="http://WebXml.com.cn/";  
  59.      //调用的方法名  
  60.      String methodName="getMobileCodeInfo";  
  61.      //将方法名和名称空间绑定在一起  
  62.   String SOAP_ACTION = nameSpace + methodName;  
  63. //获得返回请求对象  
  64. SoapObject request = new SoapObject(nameSpace, methodName);  
  65. //设置需要返回请求对象的参数  
  66.   request.addProperty("mobileCode", phoneName);  
  67.   request.addProperty("userId", "");  
  68.   //设置soap的版本  
  69.   SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(  
  70.     SoapEnvelope.VER11);  
  71.         //设置是否调用的是dotNet开发的  
  72.   envelope.dotNet = true;  
  73.   //  
  74.   envelope.bodyOut = request;  
  75.   AndroidHttpTransport hts = new AndroidHttpTransport  
  76. ("http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx");  
  77.   // web service请求  
  78.   hts.call(SOAP_ACTION, envelope);  
  79.   // 得到返回结果  
  80.   Object o = envelope.getResponse();  
  81.   result = o.toString();  
  82.    
  83.   return result;  
  84.     
  85. }  
  86. }  

 

6一、获取并使用KSOAP

Android SDK中并没有提供调用WebService的库,因此,需要使用第三方的SDK来调用WebServicePC版本的WebService库非常丰富,但这些对Android来说过于庞大。适合手机的WebService客户端的SDK有一些,比较常用的是KSOAP2

KSOAP2 地址:http://code.google.com/p/ksoap2-android/

我下载的最新的是: ksoap2-android-assembly-2.5.4-jar-with-dependencies.jar

注意:

我在使用ksoap2-android时犯了一个低级错误:使用时报错误:The import org.ksoap2 cannot be resolved 
当时分析这个问题时一直以为是Eclipse出了问题,找了好多方法都不行, 
实际是我下载的ksoap2-android-assembly-2.5.4-jar-with-dependencies.jar文件是错误的导致的,走了弯路。

 http://code.google.com/p/ksoap2-android/wiki/HowToUse?tm=2 页面 通过鼠标右键链接另存为存的是同名的一个纯文本的Html文件。而不是我们想要的。

我是在 
http://code.google.com/p/ksoap2-android/source/browse/m2-repo/com/google/code/ksoap2-android/ksoap2-android-assembly/2.5.4/ksoap2-android-assembly-2.5.4-jar-with-dependencies.jar  点 View raw file 才正确下载对应文件的。

 

 

选择我们的项目,右键菜单中 Build Path –> Add External Archives… 增加这个下载的包

 

增加好后,我们在 选择我们的项目,右键菜单中 Build Path –> Configure Build Path 的 Libraries 中可以看到下面图:

 

二,分以下几步来调用 WebService

 

1、指定 WebService 的命名空间和调用方法

import org.ksoap2.serialization.SoapObject;private static final String NAMESPACE = "http://WebXml.com.cn/";private static final String METHOD_NAME = "getWeatherbyCityName"; SoapObject rpc = new SoapObject(NAMESPACE, METHOD_NAME);

SoapObject类的第一个参数表示WebService的命名空间,可以从WSDL文档中找到WebService的命名空间。 
第二个参数表示要调用的WebService方法名。

2、设置调用方法的参数值,如果没有参数,可以省略,设置方法的参数值的代码如下:

rpc.addProperty("theCityName", "北京");

要注意的是,addProperty方法的第1个参数虽然表示调用方法的参数名,但该参数值并不一定与服务端的WebService类中的方法参数名一致,只要设置参数的顺序一致即可。

3、生成调用Webservice方法的SOAP请求信息。

SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);envelope.bodyOut = rpc;envelope.dotNet = true;envelope.setOutputSoapObject(rpc);

创建SoapSerializationEnvelope对象时需要通过SoapSerializationEnvelope类的构造方法设置SOAP协议的版本号。 
该版本号需要根据服务端WebService的版本号设置。 
在创建SoapSerializationEnvelope对象后,不要忘了设置SOAPSoapSerializationEnvelope类的bodyOut属性, 
该属性的值就是在第一步创建的SoapObject对象。

4、创建HttpTransportsSE对象。

这里不要使用 AndroidHttpTransport ht = new AndroidHttpTransport(URL); 这是一个要过期的类

private static String URL = "http://www.webxml.com.cn/webservices/weatherwebservice.asmx";HttpTransportSE ht = new HttpTransportSE(URL); 

ht.debug = true;

5、使用call方法调用WebService方法

private static String SOAP_ACTION = "http://WebXml.com.cn/getWeatherbyCityName";ht.call(SOAP_ACTION, envelope);

网上有人说这里的call的第一个参数为null,但是经过我的测试,null是不行的。 
2个参数就是在第3步创建的SoapSerializationEnvelope对象。

6、获得WebService方法的返回结果

有两种方法:

1、使用getResponse方法获得返回数据。

private SoapObject detail;detail =(SoapObject) envelope.getResponse();

2、使用 bodyIn 及 getProperty

private SoapObject detail;SoapObject result = (SoapObject)envelope.bodyIn;detail = (SoapObject) result.getProperty("getWeatherbyCityNameResult");

7、 这时候执行会出错,提示没有权限访问网络

需要修改 AndroidManifest.xml 文件,赋予相应权限

简单来说就是增加下面这行配置:<uses-permission android:name="android.permission.INTERNET"></uses-permission>

完整的 AndroidManifest.xml 文件 如下:

 

注:Android 中在代码中为了调试写了system.out.print()输出项

在菜单:Window-->show view-->other-->找到Android,选择Logcat 是可以看到输出的
如果你想在一个单独的窗口看到system.out.print()的输出的话,可以在logcat界面点那个绿色的“+”好,

Filter name 和 By log tag里面均填入System.out,这样的话你就能在单独的界面查看system.out.print()的输出了!!

<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android" package="ghj1976.MyWeather" android:versionCode="1" android:versionName="1.0">  <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".MyWeatherActivity" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> <uses-permission android:name="android.permission.INTERNET"></uses-permission> </manifest>

完整的代码如下:

package ghj1976.MyWeather;import java.io.UnsupportedEncodingException;import android.app.Activity;import android.os.Bundle;import android.view.View;import android.widget.Button;import android.widget.Toast;import org.ksoap2.SoapEnvelope;import org.ksoap2.serialization.SoapObject;import org.ksoap2.serialization.SoapSerializationEnvelope;//import org.ksoap2.transport.AndroidHttpTransport;import org.ksoap2.transport.HttpTransportSE;public class MyWeatherActivity extends Activity {  private Button okButton;  /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); okButton = (Button) this.findViewById(R.id.btn_Search); okButton.setOnClickListener(new Button.OnClickListener() { @Override public void onClick(View v) {   String city = "北京";   getWeather(city);   }  }); }  private static final String NAMESPACE = "http://WebXml.com.cn/";  // WebService地址 private static String URL = "http://www.webxml.com.cn/webservices/weatherwebservice.asmx";  private static final String METHOD_NAME = "getWeatherbyCityName";  private static String SOAP_ACTION = "http://WebXml.com.cn/getWeatherbyCityName";  private String weatherToday;  private SoapObject detail;  public void getWeather(String cityName) { try { System.out.println("rpc------"); SoapObject rpc = new SoapObject(NAMESPACE, METHOD_NAME); System.out.println("rpc" + rpc); System.out.println("cityName is " + cityName); rpc.addProperty("theCityName", cityName);  SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11); envelope.bodyOut = rpc; envelope.dotNet = true; envelope.setOutputSoapObject(rpc); HttpTransportSE ht = new HttpTransportSE(URL);  //AndroidHttpTransport ht = new AndroidHttpTransport(URL); ht.debug = true;  ht.call(SOAP_ACTION, envelope); //ht.call(null, envelope);  //SoapObject result = (SoapObject)envelope.bodyIn; //detail = (SoapObject) result.getProperty("getWeatherbyCityNameResult");  detail =(SoapObject) envelope.getResponse(); //System.out.println("result" + result); System.out.println("detail" + detail); Toast.makeText(this, detail.toString(), Toast.LENGTH_LONG).show(); parseWeather(detail);  return; } catch (Exception e) { e.printStackTrace(); } }  private void parseWeather(SoapObject detail) throws UnsupportedEncodingException { String date = detail.getProperty(6).toString(); weatherToday = "今天:" + date.split(" ")[0]; weatherToday = weatherToday + "\n天气:" + date.split(" ")[1]; weatherToday = weatherToday + "\n气温:" + detail.getProperty(5).toString(); weatherToday = weatherToday + "\n风力:" + detail.getProperty(7).toString() + "\n"; System.out.println("weatherToday is " + weatherToday); Toast.makeText(this, weatherToday, Toast.LENGTH_LONG).show();  }}

参考资料

Android中访问WebService接口 
http://www.cnblogs.com/yy-7years/archive/2011/01/24/1943286.html

Android调用WebService 
http://express.ruanko.com/ruanko-express_34/technologyexchange5.html

中国气象局的WebService地址 
http://www.webxml.com.cn/WebServices/WeatherWebService.asmx

Android与服务器端数据交互(基于SOAP协议整合android+webservice 
http://www.cnblogs.com/zhangdongzi/archive/2011/04/19/2020688.html

版权声明:本文为博主原创文章,未经博主允许不得转载。

 

7[java] view plaincopy

  1. 在android程序中运行第一步就是检测当前有无可用网络   
  2. 如果没有网络可用就退出程序   
  3. if (isConnect(this)==false)   
  4. {     
  5. new AlertDialog.Builder(this)   
  6. .setTitle("网络错误")   
  7. .setMessage("网络连接失败,请确认网络连接")   
  8. .setPositiveButton("确定", new DialogInterface.OnClickListener() {   
  9. @Override   
  10. public void onClick(DialogInterface arg0, int arg1) {   
  11. // TODO Auto-generated method stub   
  12. android.os.Process.killProcess(android.os.Process.myPid());   
  13. System.exit(0);   
  14. }   
  15. }).show();   
  16. }   
  17. public static boolean isConnect(Context context) {   
  18. // 获取手机所有连接管理对象(包括对wi-fi,net等连接的管理)   
  19. try {   
  20. ConnectivityManager connectivity = (ConnectivityManager) context   
  21. .getSystemService(Context.CONNECTIVITY_SERVICE);   
  22. if (connectivity != null) {   
  23. // 获取网络连接管理的对象   
  24. NetworkInfo info = connectivity.getActiveNetworkInfo();   
  25. if (info != null&& info.isConnected()) {   
  26. // 判断当前网络是否已经连接   
  27. if (info.getState() == NetworkInfo.State.CONNECTED) {   
  28. return true;   
  29. }   
  30. }   
  31. }   
  32. } catch (Exception e) {   
  33. // TODO: handle exception   
  34. Log.v("error",e.toString());   
  35. }   
  36. return false;   
  37. }   
  38. 最后一点还得再manifest中添加权限   
  39. <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>  

8[java] view plaincopy

  1. public class MainActivity extends Activity     
  2. {    
  3. private static final String TAG = "MainActivity";    
  4. private EditText timelengthText;    
  5. private EditText titleText;    
  6. private EditText videoText;    
  7. @Override    
  8. public void onCreate(Bundle savedInstanceState)     
  9. {    
  10. super.onCreate(savedInstanceState);    
  11. setContentView(R.layout.main);    
  12. //提交上传按钮    
  13. Button button = (Button) this.findViewById(R.id.button);    
  14. timelengthText = (EditText) this.findViewById(R.id.timelength);    
  15. videoText = (EditText) this.findViewById(R.id.video);    
  16. titleText = (EditText) this.findViewById(R.id.title);    
  17. button.setOnClickListener(new View.OnClickListener()     
  18. {                
  19. @Override    
  20. public void onClick(View v)     
  21. {    
  22. String title = titleText.getText().toString();    
  23. String timelength = timelengthText.getText().toString();    
  24. Map<String, String> params = new HashMap<String, String>();    
  25. params.put("method", "save");    
  26. params.put("title", title);    
  27. params.put("timelength", timelength);    
  28. try     
  29. {                       
  30. //得到SDCard的目录    
  31. File uploadFile = new File(Environment.getExternalStorageDirectory(), videoText.getText().toString());    
  32. //上传音频文件    
  33. FormFile formfile = new FormFile("02.mp3", uploadFile, "video", "audio/mpeg");    
  34. SocketHttpRequester.post("http://192.168.1.100:8080/videoweb/video/manage.do", params, formfile);    
  35. Toast.makeText(MainActivity.this, R.string.success, 1).show();    
  36. }    
  37. catch (Exception e)     
  38. {    
  39. Toast.makeText(MainActivity.this, R.string.error, 1).show();    
  40. Log.e(TAG, e.toString());    
  41. }    
  42. }    
  43. });            
  44. }    
  45. }    

[java] view plaincopy

  1. .上传工具类,注意里面构造协议字符串需要根据不同的提交表单来处理  
  2. public class SocketHttpRequester     
  3. {    
  4. /**  
  5. * 发送xml数据  
  6. * @param path 请求地址  
  7. * @param xml xml数据  
  8. * @param encoding 编码  
  9. * @return  
  10. * @throws Exception  
  11. */    
  12. public static byte[] postXml(String path, String xml, String encoding) throws Exception{    
  13. byte[] data = xml.getBytes(encoding);    
  14. URL url = new URL(path);    
  15. HttpURLConnection conn = (HttpURLConnection)url.openConnection();    
  16. conn.setRequestMethod("POST");    
  17. conn.setDoOutput(true);    
  18. conn.setRequestProperty("Content-Type", "text/xml; charset="+ encoding);    
  19. conn.setRequestProperty("Content-Length", String.valueOf(data.length));    
  20. conn.setConnectTimeout(5 * 1000);    
  21. OutputStream outStream = conn.getOutputStream();    
  22. outStream.write(data);    
  23. outStream.flush();    
  24. outStream.close();    
  25. if(conn.getResponseCode()==200){    
  26. return readStream(conn.getInputStream());    
  27. }    
  28. return null;    
  29. }    
  30. /**  
  31. * 直接通过HTTP协议提交数据到服务器,实现如下面表单提交功能:  
  32. *   <FORM METHOD=POST ACTION="http://192.168.0.200:8080/ssi/fileload/test.do" enctype="multipart/form-data">  
  33. <INPUT TYPE="text" NAME="name">  
  34. <INPUT TYPE="text" NAME="id">  
  35. <input type="file" name="imagefile"/>  
  36. <input type="file" name="zip"/>  
  37. </FORM>  
  38. * @param path 上传路径(注:避免使用localhost或127.0.0.1这样的路径测试,  
  39. *                  因为它会指向手机模拟器,你可以使用http://www.baidu.com或http://192.168.1.10:8080这样的路径测试)  
  40. * @param params 请求参数 key为参数名,value为参数值  
  41. * @param file 上传文件  
  42. */    
  43. public static boolean post(String path, Map<String, String> params, FormFile[] files) throws Exception    
  44. {       
  45. //数据分隔线    
  46. final String BOUNDARY = "---------------------------7da2137580612";     
  47. //数据结束标志"---------------------------7da2137580612--"    
  48. final String endline = "--" + BOUNDARY + "--/r/n";    
  49. //下面两个for循环都是为了得到数据长度参数,依据表单的类型而定    
  50. //首先得到文件类型数据的总长度(包括文件分割线)    
  51. int fileDataLength = 0;    
  52. for(FormFile uploadFile : files)    
  53. {    
  54. StringBuilder fileExplain = new StringBuilder();    
  55. fileExplain.append("--");    
  56. fileExplain.append(BOUNDARY);    
  57. fileExplain.append("/r/n");    
  58. fileExplain.append("Content-Disposition: form-data;name=/""+ uploadFile.getParameterName()+"/";filename=/""+ uploadFile.getFilname() + "/"/r/n");    
  59. fileExplain.append("Content-Type: "+ uploadFile.getContentType()+"/r/n/r/n");    
  60. fileExplain.append("/r/n");    
  61. fileDataLength += fileExplain.length();    
  62. if(uploadFile.getInStream()!=null){    
  63. fileDataLength += uploadFile.getFile().length();    
  64. }else{    
  65. fileDataLength += uploadFile.getData().length;    
  66. }    
  67. }    
  68. //再构造文本类型参数的实体数据    
  69. StringBuilder textEntity = new StringBuilder();            
  70. for (Map.Entry<String, String> entry : params.entrySet())     
  71. {      
  72. textEntity.append("--");    
  73. textEntity.append(BOUNDARY);    
  74. textEntity.append("/r/n");    
  75. textEntity.append("Content-Disposition: form-data; name=/""+ entry.getKey() + "/"/r/n/r/n");    
  76. textEntity.append(entry.getValue());    
  77. textEntity.append("/r/n");    
  78. }    
  79. //计算传输给服务器的实体数据总长度(文本总长度+数据总长度+分隔符)    
  80. int dataLength = textEntity.toString().getBytes().length + fileDataLength +  endline.getBytes().length;    
  81. URL url = new URL(path);    
  82. //默认端口号其实可以不写    
  83. int port = url.getPort()==-1 ? 80 : url.getPort();    
  84. //建立一个Socket链接    
  85. Socket socket = new Socket(InetAddress.getByName(url.getHost()), port);    
  86. //获得一个输出流(从Android流到web)    
  87. OutputStream outStream = socket.getOutputStream();    
  88. //下面完成HTTP请求头的发送    
  89. String requestmethod = "POST "+ url.getPath()+" HTTP/1.1/r/n";    
  90. outStream.write(requestmethod.getBytes());    
  91. //构建accept    
  92. String accept = "Accept: image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/xaml+xml, application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*/r/n";    
  93. outStream.write(accept.getBytes());    
  94. //构建language    
  95. String language = "Accept-Language: zh-CN/r/n";    
  96. outStream.write(language.getBytes());    
  97. //构建contenttype    
  98. String contenttype = "Content-Type: multipart/form-data; boundary="+ BOUNDARY+ "/r/n";    
  99. outStream.write(contenttype.getBytes());    
  100. //构建contentlength    
  101. String contentlength = "Content-Length: "+ dataLength + "/r/n";    
  102. outStream.write(contentlength.getBytes());    
  103. //构建alive    
  104. String alive = "Connection: Keep-Alive/r/n";            
  105. outStream.write(alive.getBytes());    
  106. //构建host    
  107. String host = "Host: "+ url.getHost() +":"+ port +"/r/n";    
  108. outStream.write(host.getBytes());    
  109. //写完HTTP请求头后根据HTTP协议再写一个回车换行    
  110. outStream.write("/r/n".getBytes());    
  111. //把所有文本类型的实体数据发送出来    
  112. outStream.write(textEntity.toString().getBytes());             
  113. //把所有文件类型的实体数据发送出来    
  114. for(FormFile uploadFile : files)    
  115. {    
  116. StringBuilder fileEntity = new StringBuilder();    
  117. fileEntity.append("--");    
  118. fileEntity.append(BOUNDARY);    
  119. fileEntity.append("/r/n");    
  120. fileEntity.append("Content-Disposition: form-data;name=/""+ uploadFile.getParameterName()+"/";filename=/""+ uploadFile.getFilname() + "/"/r/n");    
  121. fileEntity.append("Content-Type: "+ uploadFile.getContentType()+"/r/n/r/n");    
  122. outStream.write(fileEntity.toString().getBytes());    
  123. //边读边写    
  124. if(uploadFile.getInStream()!=null)    
  125. {    
  126. byte[] buffer = new byte[1024];    
  127. int len = 0;    
  128. while((len = uploadFile.getInStream().read(buffer, 0, 1024))!=-1)    
  129. {    
  130. outStream.write(buffer, 0, len);    
  131. }    
  132. uploadFile.getInStream().close();    
  133. }    
  134. else    
  135. {    
  136. outStream.write(uploadFile.getData(), 0, uploadFile.getData().length);    
  137. }    
  138. outStream.write("/r/n".getBytes());    
  139. }    
  140. //下面发送数据结束标志,表示数据已经结束    
  141. outStream.write(endline.getBytes());            
  142. BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));    
  143. //读取web服务器返回的数据,判断请求码是否为200,如果不是200,代表请求失败    
  144. if(reader.readLine().indexOf("200")==-1)    
  145. {    
  146. return false;    
  147. }    
  148. outStream.flush();    
  149. outStream.close();    
  150. reader.close();    
  151. socket.close();    
  152. return true;    
  153. }    
  154. /**    
  155. * 提交数据到服务器    
  156. * @param path 上传路径(注:避免使用localhost或127.0.0.1这样的路径测试,因为它会指向手机模拟器,你可以使用http://www.baidu.com或http://192.168.1.10:8080这样的路径测试)    
  157. * @param params 请求参数 key为参数名,value为参数值    
  158. * @param file 上传文件    
  159. */    
  160. public static boolean post(String path, Map<String, String> params, FormFile file) throws Exception    
  161. {    
  162. return post(path, params, new FormFile[]{file});    
  163. }    
  164. /**  
  165. * 提交数据到服务器  
  166. * @param path 上传路径(注:避免使用localhost或127.0.0.1这样的路径测试,因为它会指向手机模拟器,你可以使用http://www.baidu.com或http://192.168.1.10:8080这样的路径测试)  
  167. * @param params 请求参数 key为参数名,value为参数值  
  168. * @param encode 编码  
  169. */    
  170. public static byte[] postFromHttpClient(String path, Map<String, String> params, String encode) throws Exception    
  171. {    
  172. //用于存放请求参数    
  173. List<NameValuePair> formparams = new ArrayList<NameValuePair>();    
  174. for(Map.Entry<String, String> entry : params.entrySet())    
  175. {    
  176. formparams.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));    
  177. }    
  178. UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formparams, encode);    
  179. HttpPost httppost = new HttpPost(path);    
  180. httppost.setEntity(entity);    
  181. //看作是浏览器    
  182. HttpClient httpclient = new DefaultHttpClient();    
  183. //发送post请求      
  184. HttpResponse response = httpclient.execute(httppost);       
  185. return readStream(response.getEntity().getContent());    
  186. }    
  187. /**  
  188. * 发送请求  
  189. * @param path 请求路径  
  190. * @param params 请求参数 key为参数名称 value为参数值  
  191. * @param encode 请求参数的编码  
  192. */    
  193. public static byte[] post(String path, Map<String, String> params, String encode) throws Exception    
  194. {    
  195. //String params = "method=save&name="+ URLEncoder.encode("老毕", "UTF-8")+ "&age=28&";//需要发送的参数    
  196. StringBuilder parambuilder = new StringBuilder("");    
  197. if(params!=null && !params.isEmpty())    
  198. {    
  199. for(Map.Entry<String, String> entry : params.entrySet())    
  200. {    
  201. parambuilder.append(entry.getKey()).append("=")    
  202. .append(URLEncoder.encode(entry.getValue(), encode)).append("&");    
  203. }    
  204. parambuilder.deleteCharAt(parambuilder.length()-1);    
  205. }    
  206. byte[] data = parambuilder.toString().getBytes();    
  207. URL url = new URL(path);    
  208. HttpURLConnection conn = (HttpURLConnection)url.openConnection();    
  209. //设置允许对外发送请求参数    
  210. conn.setDoOutput(true);    
  211. //设置不进行缓存    
  212. conn.setUseCaches(false);    
  213. conn.setConnectTimeout(5 * 1000);    
  214. conn.setRequestMethod("POST");    
  215. //下面设置http请求头    
  216. conn.setRequestProperty("Accept", "image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/xaml+xml, application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*");    
  217. conn.setRequestProperty("Accept-Language", "zh-CN");    
  218. conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)");    
  219. conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");    
  220. conn.setRequestProperty("Content-Length", String.valueOf(data.length));    
  221. conn.setRequestProperty("Connection", "Keep-Alive");    
  222. //发送参数    
  223. DataOutputStream outStream = new DataOutputStream(conn.getOutputStream());    
  224. outStream.write(data);//把参数发送出去    
  225. outStream.flush();    
  226. outStream.close();    
  227. if(conn.getResponseCode()==200)    
  228. {    
  229. return readStream(conn.getInputStream());    
  230. }    
  231. return null;    
  232. }    
  233. /**    
  234. * 读取流    
  235. * @param inStream    
  236. * @return 字节数组    
  237. * @throws Exception    
  238. */    
  239. public static byte[] readStream(InputStream inStream) throws Exception    
  240. {    
  241. ByteArrayOutputStream outSteam = new ByteArrayOutputStream();    
  242. byte[] buffer = new byte[1024];    
  243. int len = -1;    
  244. while( (len=inStream.read(buffer)) != -1)    
  245. {    
  246. outSteam.write(buffer, 0, len);    
  247. }    
  248. outSteam.close();    
  249. inStream.close();    
  250. return outSteam.toByteArray();    
  251. }    
  252. }    

 

[java] view plaincopy

  1. public class StreamTool     
  2. {    
  3. /**  
  4. * 从输入流读取数据  
  5. * @param inStream  
  6. * @return  
  7. * @throws Exception  
  8. */    
  9. public static byte[] readInputStream(InputStream inStream) throws Exception{    
  10. ByteArrayOutputStream outSteam = new ByteArrayOutputStream();    
  11. byte[] buffer = new byte[1024];    
  12. int len = 0;    
  13. while( (len = inStream.read(buffer)) !=-1 ){    
  14. outSteam.write(buffer, 0, len);    
  15. }    
  16. outSteam.close();    
  17. inStream.close();    
  18. return outSteam.toByteArray();    
  19. }    
  20. }    

 

[java] view plaincopy

  1. /**  
  2. * 使用JavaBean封装上传文件数据  
  3. *   
  4. */    
  5. public class FormFile     
  6. {    
  7. //上传文件的数据     
  8. private byte[] data;    
  9. private InputStream inStream;    
  10. private File file;    
  11. //文件名称     
  12. private String filname;    
  13. //请求参数名称    
  14. private String parameterName;    
  15. //内容类型    
  16. private String contentType = "application/octet-stream";    
  17. /**  
  18. * 上传小文件,把文件数据先读入内存  
  19. * @param filname  
  20. * @param data  
  21. * @param parameterName  
  22. * @param contentType  
  23. */    
  24. public FormFile(String filname, byte[] data, String parameterName, String contentType)     
  25. {    
  26. this.data = data;    
  27. this.filname = filname;    
  28. this.parameterName = parameterName;    
  29. if(contentType!=null) this.contentType = contentType;    
  30. }    
  31. /**  
  32. * 上传大文件,一边读文件数据一边上传  
  33. * @param filname  
  34. * @param file  
  35. * @param parameterName  
  36. * @param contentType  
  37. */    
  38. public FormFile(String filname, File file, String parameterName, String contentType)     
  39. {    
  40. this.filname = filname;    
  41. this.parameterName = parameterName;    
  42. this.file = file;    
  43. try     
  44. {    
  45. this.inStream = new FileInputStream(file);    
  46. }    
  47. catch (FileNotFoundException e)     
  48. {    
  49. e.printStackTrace();    
  50. }    
  51. if(contentType!=null) this.contentType = contentType;    
  52. }    
  53. public File getFile()     
  54. {    
  55. return file;    
  56. }    
  57. public InputStream getInStream()     
  58. {    
  59. return inStream;    
  60. }    
  61. public byte[] getData()     
  62. {    
  63. return data;    
  64. }    
  65. public String getFilname()     
  66. {    
  67. return filname;    
  68. }    
  69. public void setFilname(String filname)    
  70. {    
  71. this.filname = filname;    
  72. }    
  73. public String getParameterName()     
  74. {    
  75. return parameterName;    
  76. }    
  77. public void setParameterName(String parameterName)     
  78. {    
  79. this.parameterName = parameterName;    
  80. }    
  81. public String getContentType()    
  82. {    
  83. return contentType;    
  84. }    
  85. public void setContentType(String contentType)     
  86. {    
  87. this.contentType = contentType;    
  88. }       
  89. }    

 

9[java] view plaincopy

  1. 对于Android流量统计来说在2.2版中新加入了TrafficStats类可以轻松获取,其实本身TrafficStats类也是读取Linux提供的文件对象系统类型的文本进行解析。android.net.TrafficStats类中,提供了多种静态方法,可以直接调用获取,返回类型均为 long型,如果返回等于-1代表 UNSUPPORTED 当前设备不支持统计。   
  2. Java代码    
  3. static long  getMobileRxBytes()  //获取通过Mobile连接收到的字节总数,不包含WiFi    
  4. static long  getMobileRxPackets()  //获取Mobile连接收到的数据包总数    
  5. static long  getMobileTxBytes()  //Mobile发送的总字节数    
  6. static long  getMobileTxPackets()  //Mobile发送的总数据包数    
  7. static long  getTotalRxBytes()  //获取总的接受字节数,包含Mobile和WiFi等    
  8. static long  getTotalRxPackets()  //总的接受数据包数,包含Mobile和WiFi等    
  9. static long  getTotalTxBytes()  //总的发送字节数,包含Mobile和WiFi等    
  10. static long  getTotalTxPackets()  //发送的总数据包数,包含Mobile和WiFi等     
  11. static long  getUidRxBytes(int uid)  //获取某个网络UID的接受字节数    
  12. static long  getUidTxBytes(int uid) //获取某个网络UID的发送字节数     
  13. 总接受流量TrafficStats.getTotalRxBytes(),   
  14. 总发送流量TrafficStats.getTotalTxBytes());   
  15. 不包含WIFI的手机GPRS接收量TrafficStats.getMobileRxBytes());   
  16. 不包含Wifi的手机GPRS发送量TrafficStats.getMobileTxBytes());   
  17. 某一个进程的总接收量TrafficStats.getUidRxBytes(Uid));   
  18. 某一个进程的总发送量TrafficStats.getUidTxBytes(Uid));   
  19. 这些都是从第一次启动程序到最后一次启动的统计量。并不是这篇文章里所说的“从本次开机到本次关机的统计量”!   
  20. 用法举例,注意这里得到的单位都是"KB"   
  21. Java代码    
  22. public long getTotalRxBytes(){  //获取总的接受字节数,包含Mobile和WiFi等    
  23. return TrafficStats.getTotalRxBytes()==TrafficStats.UNSUPPORTED?0:(TrafficStats.getTotalRxBytes()/1024);    
  24. }    
  25. public long getTotalTxBytes(){  //总的发送字节数,包含Mobile和WiFi等    
  26. return TrafficStats.getTotalTxBytes()==TrafficStats.UNSUPPORTED?0:(TrafficStats.getTotalTxBytes()/1024);    
  27. }    
  28. public long getMobileRxBytes(){  //获取通过Mobile连接收到的字节总数,不包含WiFi    
  29. return TrafficStats.getMobileRxBytes()==TrafficStats.UNSUPPORTED?0:(TrafficStats.getMobileRxBytes()/1024);    
  30. }    

10Android开发应用程序时,如果应用程序需要访问网络权限,需要在 AndroidManifest.xml 中加入以下代码<uses-permission android:name=”android.permission.INTERNET”></uses-permission>

如果不知道放在哪个位置,那就放在</manifest>前边好了。

同样的如果用到其它的权限,也需要作出声明,部分权限列表如下:

android.permission.ACCESS_CHECKIN_PROPERTIES

允许读写访问”properties”表在 checkin数据库中,改值可以修改上传( Allows read/write access to the “properties” table in the checkin database, to change values that get uploaded)

android.permission.ACCESS_COARSE_LOCATION

允许一个程序访问CellIDWiFi热点来获取粗略的位置(Allows an application to access coarse (e.g., Cell-ID, WiFi) location)

android.permission.ACCESS_FINE_LOCATION

允许一个程序访问精良位置(GPS) (Allows an application to access fine (e.g., GPS) location)

android.permission.ACCESS_LOCATION_EXTRA_COMMANDS

允许应用程序访问额外的位置提供命令(Allows an application to access extra location provider commands)

android.permission.ACCESS_MOCK_LOCATION

允许程序创建模拟位置提供用于测试(Allows an application to create mock location providers for testing)

android.permission.ACCESS_NETWORK_STATE

允许程序访问有关GSM网络信息(Allows applications to access information about networks)

android.permission.ACCESS_SURFACE_FLINGER

允许程序使用SurfaceFlinger底层特性 (Allows an application to use SurfaceFlinger’s low level features)

android.permission.ACCESS_WIFI_STATE

允许程序访问Wi-Fi网络状态信息(Allows applications to access information about Wi-Fi networks)

android.permission.ADD_SYSTEM_SERVICE

允许程序发布系统级服务(Allows an application to publish system-level services).

android.permission.BATTERY_STATS

允许程序更新手机电池统计信息(Allows an application to update the collected battery statistics)

android.permission.BLUETOOTH

允许程序连接到已配对的蓝牙设备(Allows applications to connect to paired bluetooth devices)

11不说废话,直接说说实现android定位有关的API吧。

这些API都在android.location包下,一共有三个接口和八个类。它们配合使用即可实现定位功能。

三个接口:

GpsStatus.Listener:这是一个当GPS状态发生改变时,用来接收通知的接口。

GpsStatus.NmeaListener:这是一个用来从GPS里接收Nmea-0183(为海用电子设备制定的标准格式)信息的接口。

LocationListener:位置监听器,用于接收当位置信息发生改变时从LocationManager接收通知的接口。

八个类:

Address:描述地址的类,比如:北京天安门

Criteria:用于描述Location Provider标准的类,标准包括位置精度水平,电量消耗水平,是否获取海拔、方位信息,是否允许接收付费服务。

GeoCoder:用于处理地理位置的编码。

GpsSatellite:和GpsStatus联合使用,用于描述当前GPS卫星的状态。

GpsStatus:和GpsStatus.Listener联合使用,用于描述当前GPS卫星的状态。

Location:用于描述位置信息。

LocationManager:通过此类获取和调用系统位置服务

LocationProvider:用于描述Location Provider的抽象超类,一个LocationProvider应该能够周期性的报告当前设备的位置信息。

这里通过一个示例代码来演示一下android定位

首先,在AndroidManifest.xml清单文件里需要加入ACCESS_FINE_LOCATION权限:

?

1

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"></uses-permission>

其次,实现代码如下:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

package com.test;

 

import java.io.IOException;

import java.util.List;

 

import android.app.Activity;

import android.location.Address;

import android.location.Criteria;

import android.location.Geocoder;

import android.location.Location;

import android.location.LocationListener;

import android.location.LocationManager;

import android.os.Bundle;

import android.util.Log;

import android.widget.Toast;

 

public class PositionActivity extends Activity {

    @Override

    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.main);

        // 获取到LocationManager对象

        LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);

        // 创建一个Criteria对象

        Criteria criteria = new Criteria();

        // 设置粗略精确度

        criteria.setAccuracy(Criteria.ACCURACY_COARSE);

        // 设置是否需要返回海拔信息

        criteria.setAltitudeRequired(false);

        // 设置是否需要返回方位信息

        criteria.setBearingRequired(false);

        // 设置是否允许付费服务

        criteria.setCostAllowed(true);

        // 设置电量消耗等级

        criteria.setPowerRequirement(Criteria.POWER_HIGH);

        // 设置是否需要返回速度信息

        criteria.setSpeedRequired(false);

        // 根据设置的Criteria对象,获取最符合此标准的provider对象 41

        String currentProvider = locationManager

                .getBestProvider(criteria, true);

        Log.d("Location", "currentProvider: " + currentProvider);

        // 根据当前provider对象获取最后一次位置信息 44

        Location currentLocation = locationManager

                .getLastKnownLocation(currentProvider);

        // 如果位置信息为null,则请求更新位置信息 46

        if (currentLocation == null) {

            locationManager.requestLocationUpdates(currentProvider, 0, 0,

                    locationListener);

        }

        // 直到获得最后一次位置信息为止,如果未获得最后一次位置信息,则显示默认经纬度 50

        // 每隔10秒获取一次位置信息 51

        while (true) {

            currentLocation = locationManager

                    .getLastKnownLocation(currentProvider);

            if (currentLocation != null) {

                Log.d("Location", "Latitude: " + currentLocation.getLatitude());

                Log.d("Location", "location: " + currentLocation.getLongitude());

                break;

            } else {

                Log.d("Location", "Latitude: " + 0);

                Log.d("Location", "location: " + 0);

            }

            try {

                Thread.sleep(10000);

            } catch (InterruptedException e) {

                Log.e("Location", e.getMessage());

            }

        }

        // 解析地址并显示 69

        Geocoder geoCoder = new Geocoder(this);

        try {

            int latitude = (int) currentLocation.getLatitude();

            int longitude = (int) currentLocation.getLongitude();

            List<Address> list = geoCoder.getFromLocation(latitude, longitude,

                    2);

            for (int i = 0; i < list.size(); i++) {

                Address address = list.get(i);

                Toast.makeText(

                        PositionActivity.this,

                        address.getCountryName() + address.getAdminArea()

                                + address.getFeatureName(), Toast.LENGTH_LONG)

                        .show();

            }

        } catch (IOException e) {

            Toast.makeText(PositionActivity.this, e.getMessage(),

                    Toast.LENGTH_LONG).show();

        }

    }

    // 创建位置监听器 85

    private LocationListener locationListener = new LocationListener() {

        // 位置发生改变时调用 87

        @Override

        public void onLocationChanged(Location location) {

            Log.d("Location", "onLocationChanged");

            Log.d("Location",

                    "onLocationChanged Latitude" + location.getLatitude());

            Log.d("Location",

                    "onLocationChanged location" + location.getLongitude());

        }

 

        // provider失效时调用 95

        @Override

        public void onProviderDisabled(String provider) {

            Log.d("Location", "onProviderDisabled");

        }

 

        // provider启用时调用101

        @Override

        public void onProviderEnabled(String provider) {

            Log.d("Location", "onProviderEnabled");

        }

 

        // 状态改变时调用107

        @Override

        public void onStatusChanged(String provider, int status, Bundle extras) {

            Log.d("Location", "onStatusChanged");

        }

    };

}

由于代码里的Criteria对象对位置精度要求并不高,所以一般会返回“network”作为provider,而基于network的定位往往会存在一定的位置偏差,这对于需要精确定位的应用程序来说,显然不合要求。这时,需要则需要用到基于GPS的定位方法了

12在前文Android定位功能(一)中,已经大致介绍了一下在Android平台中,和定位功能相关的类,并举例获取了位置信息。但是前文是基于Criteria定制了一个标准,通过getBestProvider()方法由Android系统自动获取最符合CriteriaLocationProvider,从而实现了定位功能。这样的做法能最大限度的保证定位功能的可实现性,但是却无法保证获取到的位置信息有最大的准确度。因为除了GPS外,其他定位方式都或多或少存在着位置偏移。

在实现GPS定位前,先了解一下GPS的部分特性:

1GPS定位需要依靠3颗或以上的卫星。

2GPS定位受环境影响较大,在晴朗的空地上,较容易搜索到卫星,而在室内通常是无法搜索到卫星的。

3GPS定位需要使用GPS功能模块,而GPS功能模块的耗电量是巨大的。

Android系统中,实现GPS定位的思路大致是:

1、获取GPSLocation Provider

2、将此Provider传入到requestLocationUpdates()方法,让Android系统获知搜索位置方式。

3、创建实现了GpsStatus.Listener接口的对象,重写onGpsStatusChanged()方法,向LocationManager添加次监听器,检测卫星状态。(可选步骤)

根据以上思路,仿照Android定位功能(一)中的例子,可以很容易的得到以下实现代码:(此代码的实现前提是GPS功能模块处于打开状态)

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

public class MainActivity extends Activity {

    private LocationManager locationManager;

    private GpsStatus gpsstatus;

 

    @Override

    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.main);

 

        // 获取到LocationManager对象

        locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);

 

        // 根据设置的Criteria对象,获取最符合此标准的provider对象

        String currentProvider = locationManager.getProvider(

                LocationManager.GPS_PROVIDER).getName();

 

        // 根据当前provider对象获取最后一次位置信息

        Location currentLocation = locationManager

                .getLastKnownLocation(currentProvider);

        // 如果位置信息为null,则请求更新位置信息

        if (currentLocation == null) {

            locationManager.requestLocationUpdates(currentProvider, 0, 0,

                    locationListener);

        }

        // 增加GPS状态监听器

        locationManager.addGpsStatusListener(gpsListener);

 

        // 直到获得最后一次位置信息为止,如果未获得最后一次位置信息,则显示默认经纬度

        // 每隔10秒获取一次位置信息

        while (true) {

            currentLocation = locationManager

                    .getLastKnownLocation(currentProvider);

            if (currentLocation != null) {

                Log.d("Location", "Latitude: " + currentLocation.getLatitude());

                Log.d("Location", "location: " + currentLocation.getLongitude());

                break;

            } else {

                Log.d("Location", "Latitude: " + 0);

                Log.d("Location", "location: " + 0);

            }

            try {

                Thread.sleep(10000);

            } catch (InterruptedException e) {

                Log.e("Location", e.getMessage());

            }

        }

    }

 

    private GpsStatus.Listener gpsListener = new GpsStatus.Listener() {

        // GPS状态发生变化时触发

        @Override

        public void onGpsStatusChanged(int event) {

            // 获取当前状态

            gpsstatus = locationManager.getGpsStatus(null);

            switch (event) {

            // 第一次定位时的事件

            case GpsStatus.GPS_EVENT_FIRST_FIX:

                break;

            // 开始定位的事件

            case GpsStatus.GPS_EVENT_STARTED:

                break;

            // 发送GPS卫星状态事件

            case GpsStatus.GPS_EVENT_SATELLITE_STATUS:

                Toast.makeText(MainActivity.this,"GPS_EVENT_SATELLITE_STATUS",

                        Toast.LENGTH_SHORT).show();

                Iterable<GpsSatellite> allSatellites = gpsstatus

                        .getSatellites();

                Iterator<GpsSatellite> it = allSatellites.iterator();

                int count = 0;

                while (it.hasNext()) {

                    count++;

                }

                Toast.makeText(MainActivity.this, "Satellite Count:" + count,

                        Toast.LENGTH_SHORT).show();

                break;

            // 停止定位事件

            case GpsStatus.GPS_EVENT_STOPPED:

                Log.d("Location", "GPS_EVENT_STOPPED");

                break;

            }

        }

    };

 

    // 创建位置监听器

    private LocationListener locationListener = new LocationListener() {

        // 位置发生改变时调用

        @Override

        public void onLocationChanged(Location location) {

            Log.d("Location", "onLocationChanged");

        }

 

        // provider失效时调用

        @Override

        public void onProviderDisabled(String provider) {

            Log.d("Location", "onProviderDisabled");

        }

 

        // provider启用时调用

        @Override

        public void onProviderEnabled(String provider) {

            Log.d("Location", "onProviderEnabled");

        }

 

        // 状态改变时调用

        @Override

        public void onStatusChanged(String provider, int status, Bundle extras) {

            Log.d("Location", "onStatusChanged");

        }

    };

}

13[java] view plaincopy

  1. package wizzer.cn.app;  
  2. public class SecBase64 {  
  3. private static final byte[] encodingTable = { (byte) ‘A‘, (byte) ‘B‘,  
  4. (byte) ‘C‘, (byte) ‘D‘, (byte) ‘E‘, (byte) ‘F‘, (byte) ‘G‘,  
  5. (byte) ‘H‘, (byte) ‘I‘, (byte) ‘J‘, (byte) ‘K‘, (byte) ‘L‘,  
  6. (byte) ‘M‘, (byte) ‘N‘, (byte) ‘O‘, (byte) ‘P‘, (byte) ‘Q‘,  
  7. (byte) ‘R‘, (byte) ‘S‘, (byte) ‘T‘, (byte) ‘U‘, (byte) ‘V‘,  
  8. (byte) ‘W‘, (byte) ‘X‘, (byte) ‘Y‘, (byte) ‘Z‘, (byte) ‘a‘,  
  9. (byte) ‘b‘, (byte) ‘c‘, (byte) ‘d‘, (byte) ‘e‘, (byte) ‘f‘,  
  10. (byte) ‘g‘, (byte) ‘h‘, (byte) ‘i‘, (byte) ‘j‘, (byte) ‘k‘,  
  11. (byte) ‘l‘, (byte) ‘m‘, (byte) ‘n‘, (byte) ‘o‘, (byte) ‘p‘,  
  12. (byte) ‘q‘, (byte) ‘r‘, (byte) ‘s‘, (byte) ‘t‘, (byte) ‘u‘,  
  13. (byte) ‘v‘, (byte) ‘w‘, (byte) ‘x‘, (byte) ‘y‘, (byte) ‘z‘,  
  14. (byte) ‘0‘, (byte) ‘1‘, (byte) ‘2‘, (byte) ‘3‘, (byte) ‘4‘,  
  15. (byte) ‘5‘, (byte) ‘6‘, (byte) ‘7‘, (byte) ‘8‘, (byte) ‘9‘,  
  16. (byte) ‘+‘, (byte) ‘/‘ };  
  17. private static final byte[] decodingTable;  
  18. static {  
  19. decodingTable = new byte[128];  
  20. for (int i = 0; i < 128; i++) {  
  21. decodingTable[i] = (byte) -1;  
  22. }  
  23. for (int i = ‘A‘; i <= ‘Z‘; i++) {  
  24. decodingTable[i] = (byte) (i - ‘A‘);  
  25. }  
  26. for (int i = ‘a‘; i <= ‘z‘; i++) {  
  27. decodingTable[i] = (byte) (i - ‘a‘ + 26);  
  28. }  
  29. for (int i = ‘0‘; i <= ‘9‘; i++) {  
  30. decodingTable[i] = (byte) (i - ‘0‘ + 52);  
  31. }  
  32. decodingTable[‘+‘] = 62;  
  33. decodingTable[‘/‘] = 63;  
  34. }  
  35. // 加密  
  36. public static byte[] encode(byte[] data) {  
  37. byte[] bytes;  
  38. int modulus = data.length % 3;  
  39. if (modulus == 0) {  
  40. bytes = new byte[(4 * data.length) / 3];  
  41. } else {  
  42. bytes = new byte[4 * ((data.length / 3) + 1)];  
  43. }  
  44. int dataLength = (data.length - modulus);  
  45. int a1;  
  46. int a2;  
  47. int a3;  
  48. for (int i = 0, j = 0; i < dataLength; i += 3, j += 4) {  
  49. a1 = data[i] & 0xff;  
  50. a2 = data[i + 1] & 0xff;  
  51. a3 = data[i + 2] & 0xff;  
  52. bytes[j] = encodingTable[(a1 >>> 2) & 0x3f];  
  53. bytes[j + 1] = encodingTable[((a1 << 4) | (a2 >>> 4)) & 0x3f];  
  54. bytes[j + 2] = encodingTable[((a2 << 2) | (a3 >>> 6)) & 0x3f];  
  55. bytes[j + 3] = encodingTable[a3 & 0x3f];  
  56. }  
  57. int b1;  
  58. int b2;  
  59. int b3;  
  60. int d1;  
  61. int d2;  
  62. switch (modulus) {  
  63. case 0:  
  64. break;  
  65. case 1:  
  66. d1 = data[data.length - 1] & 0xff;  
  67. b1 = (d1 >>> 2) & 0x3f;  
  68. b2 = (d1 << 4) & 0x3f;  
  69. bytes[bytes.length - 4] = encodingTable[b1];  
  70. bytes[bytes.length - 3] = encodingTable[b2];  
  71. bytes[bytes.length - 2] = (byte) ‘=‘;  
  72. bytes[bytes.length - 1] = (byte) ‘=‘;  
  73. break;  
  74. case 2:  
  75. d1 = data[data.length - 2] & 0xff;  
  76. d2 = data[data.length - 1] & 0xff;  
  77. b1 = (d1 >>> 2) & 0x3f;  
  78. b2 = ((d1 << 4) | (d2 >>> 4)) & 0x3f;  
  79. b3 = (d2 << 2) & 0x3f;  
  80. bytes[bytes.length - 4] = encodingTable[b1];  
  81. bytes[bytes.length - 3] = encodingTable[b2];  
  82. bytes[bytes.length - 2] = encodingTable[b3];  
  83. bytes[bytes.length - 1] = (byte) ‘=‘;  
  84. break;  
  85. }  
  86. return bytes;  
  87. }  
  88. // 解密  
  89. public static byte[] decode(byte[] data) {  
  90. byte[] bytes;  
  91. byte b1;  
  92. byte b2;  
  93. byte b3;  
  94. byte b4;  
  95. data = discardNonBase64Bytes(data);  
  96. if (data[data.length - 2] == ‘=‘) {  
  97. bytes = new byte[(((data.length / 4) - 1) * 3) + 1];  
  98. } else if (data[data.length - 1] == ‘=‘) {  
  99. bytes = new byte[(((data.length / 4) - 1) * 3) + 2];  
  100. } else {  
  101. bytes = new byte[((data.length / 4) * 3)];  
  102. }  
  103. for (int i = 0, j = 0; i < (data.length - 4); i += 4, j += 3) {  
  104. b1 = decodingTable[data[i]];  
  105. b2 = decodingTable[data[i + 1]];  
  106. b3 = decodingTable[data[i + 2]];  
  107. b4 = decodingTable[data[i + 3]];  
  108. bytes[j] = (byte) ((b1 << 2) | (b2 >> 4));  
  109. bytes[j + 1] = (byte) ((b2 << 4) | (b3 >> 2));  
  110. bytes[j + 2] = (byte) ((b3 << 6) | b4);  
  111. }  
  112. if (data[data.length - 2] == ‘=‘) {  
  113. b1 = decodingTable[data[data.length - 4]];  
  114. b2 = decodingTable[data[data.length - 3]];  
  115. bytes[bytes.length - 1] = (byte) ((b1 << 2) | (b2 >> 4));  
  116. } else if (data[data.length - 1] == ‘=‘) {  
  117. b1 = decodingTable[data[data.length - 4]];  
  118. b2 = decodingTable[data[data.length - 3]];  
  119. b3 = decodingTable[data[data.length - 2]];  
  120. bytes[bytes.length - 2] = (byte) ((b1 << 2) | (b2 >> 4));  
  121. bytes[bytes.length - 1] = (byte) ((b2 << 4) | (b3 >> 2));  
  122. } else {  
  123. b1 = decodingTable[data[data.length - 4]];  
  124. b2 = decodingTable[data[data.length - 3]];  
  125. b3 = decodingTable[data[data.length - 2]];  
  126. b4 = decodingTable[data[data.length - 1]];  
  127. bytes[bytes.length - 3] = (byte) ((b1 << 2) | (b2 >> 4));  
  128. bytes[bytes.length - 2] = (byte) ((b2 << 4) | (b3 >> 2));  
  129. bytes[bytes.length - 1] = (byte) ((b3 << 6) | b4);  
  130. }  
  131. return bytes;  
  132. }  
  133. // 解密  
  134. public static byte[] decode(String data) {  
  135. byte[] bytes;  
  136. byte b1;  
  137. byte b2;  
  138. byte b3;  
  139. byte b4;  
  140. data = discardNonBase64Chars(data);  
  141. if (data.charAt(data.length() - 2) == ‘=‘) {  
  142. bytes = new byte[(((data.length() / 4) - 1) * 3) + 1];  
  143. } else if (data.charAt(data.length() - 1) == ‘=‘) {  
  144. bytes = new byte[(((data.length() / 4) - 1) * 3) + 2];  
  145. } else {  
  146. bytes = new byte[((data.length() / 4) * 3)];  
  147. }  
  148. for (int i = 0, j = 0; i < (data.length() - 4); i += 4, j += 3) {  
  149. b1 = decodingTable[data.charAt(i)];  
  150. b2 = decodingTable[data.charAt(i + 1)];  
  151. b3 = decodingTable[data.charAt(i + 2)];  
  152. b4 = decodingTable[data.charAt(i + 3)];  
  153. bytes[j] = (byte) ((b1 << 2) | (b2 >> 4));  
  154. bytes[j + 1] = (byte) ((b2 << 4) | (b3 >> 2));  
  155. bytes[j + 2] = (byte) ((b3 << 6) | b4);  
  156. }  
  157. if (data.charAt(data.length() - 2) == ‘=‘) {  
  158. b1 = decodingTable[data.charAt(data.length() - 4)];  
  159. b2 = decodingTable[data.charAt(data.length() - 3)];  
  160. bytes[bytes.length - 1] = (byte) ((b1 << 2) | (b2 >> 4));  
  161. } else if (data.charAt(data.length() - 1) == ‘=‘) {  
  162. b1 = decodingTable[data.charAt(data.length() - 4)];  
  163. b2 = decodingTable[data.charAt(data.length() - 3)];  
  164. b3 = decodingTable[data.charAt(data.length() - 2)];  
  165. bytes[bytes.length - 2] = (byte) ((b1 << 2) | (b2 >> 4));  
  166. bytes[bytes.length - 1] = (byte) ((b2 << 4) | (b3 >> 2));  
  167. } else {  
  168. b1 = decodingTable[data.charAt(data.length() - 4)];  
  169. b2 = decodingTable[data.charAt(data.length() - 3)];  
  170. b3 = decodingTable[data.charAt(data.length() - 2)];  
  171. b4 = decodingTable[data.charAt(data.length() - 1)];  
  172. bytes[bytes.length - 3] = (byte) ((b1 << 2) | (b2 >> 4));  
  173. bytes[bytes.length - 2] = (byte) ((b2 << 4) | (b3 >> 2));  
  174. bytes[bytes.length - 1] = (byte) ((b3 << 6) | b4);  
  175. }  
  176. return bytes;  
  177. }  
  178. private static byte[] discardNonBase64Bytes(byte[] data) {  
  179. byte[] temp = new byte[data.length];  
  180. int bytesCopied = 0;  
  181. for (int i = 0; i < data.length; i++) {  
  182. if (isValidBase64Byte(data[i])) {  
  183. temp[bytesCopied++] = data[i];  
  184. }  
  185. }  
  186. byte[] newData = new byte[bytesCopied];  
  187. System.arraycopy(temp, 0, newData, 0, bytesCopied);  
  188. return newData;  
  189. }  
  190. private static String discardNonBase64Chars(String data) {  
  191. StringBuffer sb = new StringBuffer();  
  192. int length = data.length();  
  193. for (int i = 0; i < length; i++) {  
  194. if (isValidBase64Byte((byte) (data.charAt(i)))) {  
  195. sb.append(data.charAt(i));  
  196. }  
  197. }  
  198. return sb.toString();  
  199. }  
  200. private static boolean isValidBase64Byte(byte b) {  
  201. if (b == ‘=‘) {  
  202. return true;  
  203. } else if ((b < 0) || (b >= 128)) {  
  204. return false;  
  205. } else if (decodingTable[b] == -1) {  
  206. return false;  
  207. }  
  208. return true;  
  209. }  
  210. // 测试类  
  211. public static void main(String[] args) {  
  212. String data = "wizzer@qq.com:etpass";  
  213. byte[] result = SecBase64.encode(data.getBytes());// 加密  
  214. System.out.println("Basic " + data);  
  215. System.out.println("Basic " + new String(result));  
  216. System.out.println(new String(SecBase64.decode(new String(result))));// 解密  
  217. }  
  218. }  

14登陆页面输入用户名和密码,登陆成功后跳转到主页面,失败时显示错误信息。

 

传递参数时用BasicNameValuePair的List以httpPost.setEntity的方式来做,不能用HttpParams。

 

[java] view plaincopy

  1. userName = (EditText) this.findViewById(R.id.editTextUserName);    
  2. password = (EditText) this.findViewById(R.id.editTextPassword);    
  3. errorMsg = (TextView) this.findViewById(R.id.textViewLoginMsg);    
  4. Button loginBtn = (Button) this.findViewById(R.id.btnLogin);    
  5. loginBtn.setOnClickListener(new OnClickListener() {    
  6. @Override    
  7. public void onClick(View arg0) {    
  8. String result;    
  9. /* 发送部分 */    
  10. try {    
  11. HttpClient httpClient = new DefaultHttpClient();    
  12. String address = strUrl;    
  13. HttpPost httpPost = new HttpPost(address);    
  14. List<BasicNameValuePair> params = new LinkedList<BasicNameValuePair>();    
  15. params.add(new BasicNameValuePair("username", userName.getText().toString()));    
  16. params.add(new BasicNameValuePair("password", password.getText().toString()));    
  17. httpPost.setEntity(new UrlEncodedFormEntity(params, "utf-8")); //将参数填入POST Entity中    
  18. HttpResponse httpResponse = httpClient.execute(httpPost);    
  19. /* 接收 */    
  20. if (httpResponse.getStatusLine().getStatusCode() == 200) {    
  21. result = EntityUtils.toString(httpResponse.getEntity());    
  22. /* json文本解析 */    
  23. JSONTokener jsonParser = new JSONTokener(result);    
  24. JSONObject jsonResult = (JSONObject) jsonParser.nextValue();    
  25. String status = jsonResult.getString("loginStatus");    
  26. String outMessage = jsonResult.getString("outMessage");    
  27. if(status.equals("true")){    
  28. Intent i = new Intent(LoginActivity.this, MainActivity.class);    
  29. i.putExtra("username", outMessage);    
  30. startActivityForResult(i, FIRST_REQUEST_CODE);    
  31. } else {    
  32. errorMsg.setVisibility(View.VISIBLE);    
  33. errorMsg.setText(outMessage);    
  34. }    
  35. } else {    
  36. errorMsg.setVisibility(View.VISIBLE);    
  37. errorMsg.setText("网络连接问题。CODE:" + httpResponse.getStatusLine().getStatusCode());    
  38. }    
  39. } catch (JSONException e) {    
  40. e.printStackTrace();    
  41. } catch (UnsupportedEncodingException e) {    
  42. e.printStackTrace();    
  43. } catch (ClientProtocolException e) {    
  44. e.printStackTrace();    
  45. } catch (IOException e) {    
  46. e.printStackTrace();    
  47. }    
  48. }    
  49. });    

 

15Android  Http JSon服务器端和客户端通信 
 服务器端: 

[java] view plaincopy

  1. package com.web.servlet;  
  2. import java.io.IOException;  
  3. import java.io.PrintWriter;  
  4. import java.util.ArrayList;  
  5. import java.util.Iterator;  
  6. import java.util.List;  
  7. import javax.servlet.ServletException;  
  8. import javax.servlet.http.HttpServlet;  
  9. import javax.servlet.http.HttpServletRequest;  
  10. import javax.servlet.http.HttpServletResponse;  
  11. import net.sf.json.JSONArray;  
  12. import net.sf.json.JSONObject;  
  13. import com.web.model.User;  
  14. public class JSONServlet extends HttpServlet {  
  15. /** 
  16. * Constructor of the object. 
  17. */  
  18. public JSONServlet() {  
  19. super();  
  20. }  
  21. /** 
  22. * Destruction of the servlet. <br> 
  23. */  
  24. public void destroy() {  
  25. super.destroy(); // Just puts "destroy" string in log  
  26. // Put your code here  
  27. }  
  28. /** 
  29. * The doGet method of the servlet. <br> 
  30. * This method is called when a form has its tag value method equals to get. 
  31. *  
  32. * @param request the request send by the client to the server 
  33. * @param response the response send by the server to the client 
  34. * @throws ServletException if an error occurred 
  35. * @throws IOException if an error occurred 
  36. */  
  37. public void doGet(HttpServletRequest request, HttpServletResponse response)  
  38. throws ServletException, IOException {  
  39. doPost(request, response);  
  40. }  
  41. /** 
  42. * The doPost method of the servlet. <br> 
  43. * This method is called when a form has its tag value method equals to post. 
  44. *  
  45. * @param request the request send by the client to the server 
  46. * @param response the response send by the server to the client 
  47. * @throws ServletException if an error occurred 
  48. * @throws IOException if an error occurred 
  49. */  
  50. public void doPost(HttpServletRequest request, HttpServletResponse response)  
  51. throws ServletException, IOException {  
  52. response.setContentType("text/html");  
  53. PrintWriter out = response.getWriter();  
  54. List<User> list = new ArrayList<User>();  
  55. User u1 = new User();  
  56. u1.setId(111);  
  57. u1.setUsername("zhang shan");  
  58. u1.setPassword("zs");  
  59. User u2 = new User();  
  60. u2.setId(222);  
  61. u2.setUsername("li si");  
  62. u2.setPassword("ls");  
  63. User u3 = new User();  
  64. u3.setId(333);  
  65. u3.setUsername("wang wu");  
  66. u3.setPassword("ww");  
  67. list.add(u1);  
  68. list.add(u2);  
  69. list.add(u3);  
  70. JSONArray ja = new JSONArray();  
  71. for (Iterator iterator = list.iterator(); iterator.hasNext();) {  
  72. User user = (User) iterator.next();  
  73. JSONObject jobj= new JSONObject();  
  74. jobj.put("id", user.getId());  
  75. jobj.put("username", user.getUsername());  
  76. jobj.put("password", user.getPassword());  
  77. ja.add(jobj);  
  78. }  
  79. out.write(ja.toString());     
  80. out.flush();     
  81. out.close();   
  82. }  
  83. /** 
  84. * Initialization of the servlet. <br> 
  85. * @throws ServletException if an error occurs 
  86. */  
  87. public void init() throws ServletException {  
  88. // Put your code here  
  89. }  
  90. }  

[java] view plaincopy

[java] view plaincopy

  1. 手机端:  

[java] view plaincopy

  1. package com.web.activity;  
  2. import java.io.BufferedInputStream;  
  3. import java.io.BufferedReader;  
  4. import java.io.IOException;  
  5. import java.io.InputStream;  
  6. import java.io.InputStreamReader;  
  7. import java.io.ObjectInputStream;  
  8. import java.io.UnsupportedEncodingException;  
  9. import java.util.ArrayList;  
  10. import java.util.Iterator;  
  11. import java.util.List;  
  12. import org.apache.commons.httpclient.Cookie;  
  13. import org.apache.commons.httpclient.HttpException;  
  14. import org.apache.commons.httpclient.HttpStatus;  
  15. import org.apache.commons.httpclient.NameValuePair;  
  16. import org.apache.commons.httpclient.methods.PostMethod;   
  17. import org.apache.http.HttpEntity;  
  18. import org.apache.http.HttpResponse;  
  19. import org.apache.http.client.ClientProtocolException;   
  20. import org.apache.http.client.HttpClient;  
  21. import org.apache.http.client.entity.UrlEncodedFormEntity;  
  22. import org.apache.http.client.methods.HttpGet;  
  23. import org.apache.http.client.methods.HttpPost;  
  24. import org.apache.http.client.methods.HttpUriRequest;  
  25. import org.apache.http.entity.StringEntity;  
  26. import org.apache.http.impl.client.DefaultHttpClient;  
  27. import org.apache.http.message.BasicNameValuePair;  
  28. import org.apache.http.params.HttpConnectionParams;  
  29. import org.apache.http.params.HttpParams;  
  30. import org.apache.http.protocol.HTTP;  
  31. import org.json.JSONArray;  
  32. import org.json.JSONException;  
  33. import org.json.JSONObject;  
  34. import com.web.model.User;  
  35. import android.app.Activity;  
  36. import android.os.Bundle;  
  37. import android.util.Log;  
  38. import android.view.View;  
  39. import android.view.View.OnClickListener;  
  40. import android.widget.Button;  
  41. import android.widget.EditText;  
  42. import android.widget.TextView;  
  43. public class WebclientActivity extends Activity {   
  44. private TextView hello;    
  45. @Override  
  46. public void onCreate(Bundle savedInstanceState) {  
  47. super.onCreate(savedInstanceState);  
  48. setContentView(R.layout.main);    
  49. HttpClient httpclient = new DefaultHttpClient();  
  50. String uri="http://10.11.72.108:8086/web/JSONServlet";  
  51. HttpPost httpReqest = new HttpPost(uri);     
  52. try {    
  53. HttpResponse response = httpclient.execute(httpReqest);     
  54. HttpEntity entity = response.getEntity();   
  55. BufferedReader reader = new BufferedReader(new InputStreamReader(entity.getContent()));   
  56. StringBuffer sb = new StringBuffer();       
  57. String line = null;  
  58. while ((line = reader.readLine()) != null) {  
  59. sb.append(line + "\n");  
  60. }  
  61. reader.close();   
  62. JSONArray ja = new JSONArray(sb.toString());  
  63. StringBuffer sb2 = new StringBuffer();  
  64. for (int i = 0; i < ja.length(); i++) {  
  65. JSONObject jobj= (JSONObject)ja.get(i);  
  66. sb2.append("id:").append(jobj.getInt("id")).append(" ");  
  67. sb2.append("用户:").append(jobj.getString("username")).append(" ");  
  68. sb2.append("密码:").append(jobj.getString("password")).append("\r\n");  
  69. }  
  70. TextView hello = (TextView) findViewById(R.id.helloid);  
  71. hello.setText(sb2.toString());  
  72. } catch (Exception e) {   
  73. Log.i("uuu", e.toString());  
  74. }    
  75. }   
  76. }  

 

16我们编写的是AndoridHTTP协议多线程断点下载应用程序。直接使用单线程下载HTTP文件对我们来说是一件非常简单的事。那么,多线程断点需要什么功能?

1.多线程下载,

2.支持断点。

 

使用多线程的好处:使用多线程下载会提升文件下载的速度。那么多线程下载文件的过程是: 

   (1)首先获得下载文件的长度,然后设置本地文件的长度。

       HttpURLConnection.getContentLength();//获取下载文件的长度

      RandomAccessFile file = new RandomAccessFile("QQWubiSetup.exe","rwd");

        file.setLength(filesize);//设置本地文件的长度

 

  (2)根据文件长度和线程数计算每条线程下载的数据长度和下载位置。

      如:文件的长度为6M,线程数为3,那么,每条线程下载的数据长度为2M,每条线程开始下载的位置如下图所示。

  

   例如10M大小,使用3个线程来下载,

        线程下载的数据长度   (10%3 == 0 ? 10/3:10/3+1) ,12个线程下载长度是4M,第三个线程下载长度为2M

         下载开始位置:线程id*每条线程下载的数据长度 = ?

        下载结束位置:(线程id+1*每条线程下载的数据长度-1=?

 

  (3)使用HttpRange头字段指定每条线程从文件的什么位置开始下载,下载到什么位置为止,

         如:指定从文件的2M位置开始下载,下载到位置(4M-1byte)为止

           代码如下:HttpURLConnection.setRequestProperty("Range", "bytes=2097152-4194303");

 

  (4)保存文件,使用RandomAccessFile类指定每条线程从本地文件的什么位置开始写入数据。

RandomAccessFile threadfile = new RandomAccessFile("QQWubiSetup.exe ","rwd");

threadfile.seek(2097152);//从文件的什么位置开始写入数据

 

  程序结构如下图所示:

 

 

    string.xml文件中代码:

 

 

<?xml version="1.0" encoding="utf-8"?> 

<resources>
    <string name="hello">Hello World, MainActivity!</string>
    <string name="app_name">Android网络多线程断点下载</string>
    <string name="path">下载路径</string>
    <string name="downloadbutton">下载</string>
    <string name="sdcarderror">SDCard不存在或者写保护</string>
    <string name="success">下载完成</string>
    <string name="error">下载失败</string>
</resources>

 

 

 main.xml文件中代码:

 

 

 <?xml version="1.0" encoding="utf-8"?>    

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:orientation="vertical"   

android:layout_width="fill_parent"    

android:layout_height="fill_parent">

    <!-- 下载路径 -->
    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/path"/>
    <EditText 
        android:id="@+id/path" 
        android:text="http://www.winrar.com.cn/download/wrar380sc.exe" 
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content">
    </EditText>
    <!-- 下载按钮 -->
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/downloadbutton"
        android:id="@+id/button"/>
    <!-- 进度条 -->
    <ProgressBar
        android:layout_width="fill_parent"
        android:layout_height="20dip"
        style="?android:attr/progressBarStyleHorizontal"
        android:id="@+id/downloadbar" />
    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:id="@+id/resultView" />
    </LinearLayout>

 

  

AndroidManifest.xml文件中代码:

 

 

<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android"      package="com.android.downloader"      android:versionCode="1"      android:versionName="1.0">
    <uses-sdk android:minSdkVersion="8" />

    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".MainActivity"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

    </application>
    
    <!-- SDCard中创建与删除文件权限 -->
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
    
    <!-- SDCard写入数据权限 -->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    
    <!-- 访问internet权限 -->
    <uses-permission android:name="android.permission.INTERNET"/>

</manifest>  

 


 MainActivity中代码:

 

 

package com.android.downloader;

import java.io.File;

import com.android.network.DownloadProgressListener;
import com.android.network.FileDownloader;

import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity {
    private EditText downloadpathText;
    private TextView resultView;
    private ProgressBar progressBar;
    
    /**
     * Handler被创建会关联到创建它的当前线程的消息队列,该类用于往消息队列发送消息
     * 消息队列中的消息由当前线程内部进行处理
     */
    private Handler handler = new Handler(){

        @Override
        public void handleMessage(Message msg) {            
            switch (msg.what) {
            case 1:                
                progressBar.setProgress(msg.getData().getInt("size"));
                float num = (float)progressBar.getProgress()/(float)progressBar.getMax();
                int result = (int)(num*100);
                resultView.setText(result+ "%");
                
                if(progressBar.getProgress()==progressBar.getMax()){
                    Toast.makeText(MainActivity.this, R.string.success, 1).show();
                }
                break;
            case -1:
                Toast.makeText(MainActivity.this, R.string.error, 1).show();
                break;
            }
        }
    };
    
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        downloadpathText = (EditText) this.findViewById(R.id.path);
        progressBar = (ProgressBar) this.findViewById(R.id.downloadbar);
        resultView = (TextView) this.findViewById(R.id.resultView);
        Button button = (Button) this.findViewById(R.id.button);
        
        button.setOnClickListener(new View.OnClickListener() {
            
            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                String path = downloadpathText.getText().toString();
                System.out.println(Environment.getExternalStorageState()+"------"+Environment.MEDIA_MOUNTED);
                
                if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
                    download(path, Environment.getExternalStorageDirectory());
                }else{
                    Toast.makeText(MainActivity.this, R.string.sdcarderror, 1).show();
                }
            }
        });
    }
    
      /**
       * 主线程(UI线程)
       * 对于显示控件的界面更新只是由UI线程负责,如果是在非UI线程更新控件的属性值,更新后的显示界面不会反映到屏幕上
       * @param path
       * @param savedir
       */
    private void download(final String path, final File savedir) {
        new Thread(new Runnable() {            
            @Override
            public void run() {
                FileDownloader loader = new FileDownloader(MainActivity.this, path, savedir, 3);
                progressBar.setMax(loader.getFileSize());//设置进度条的最大刻度为文件的长度
                
                try {
                    loader.download(new DownloadProgressListener() {
                        @Override
                        public void onDownloadSize(int size) {//实时获知文件已经下载的数据长度
                            Message msg = new Message();
                            msg.what = 1;
                            msg.getData().putInt("size", size);
                            handler.sendMessage(msg);//发送消息
                        }
                    });
                } catch (Exception e) {
                    handler.obtainMessage(-1).sendToTarget();
                }
            }
        }).start();
    }

}  

 

DBOpenHelper中代码:

 

 

package com.android.service;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

public class DBOpenHelper extends SQLiteOpenHelper {
    private static final String DBNAME = "down.db";
    private static final int VERSION = 1;
    
    public DBOpenHelper(Context context) {
        super(context, DBNAME, null, VERSION);
    }
    
    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL("CREATE TABLE IF NOT EXISTS filedownlog (id integer primary key autoincrement, downpath varchar(100), threadid INTEGER, downlength INTEGER)");
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL("DROP TABLE IF EXISTS filedownlog");
        onCreate(db);
    }
}

 

    

FileService中代码:

 

 

package com.android.service;

import java.util.HashMap;
import java.util.Map;

import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

public class FileService {
    private DBOpenHelper openHelper;

    public FileService(Context context) {
        openHelper = new DBOpenHelper(context);
    }
    
    /**
     * 获取每条线程已经下载的文件长度
     * @param path
     * @return
     */
    public Map<Integer, Integer> getData(String path){
        SQLiteDatabase db = openHelper.getReadableDatabase();
        Cursor cursor = db.rawQuery("select threadid, downlength from filedownlog where downpath=?", new String[]{path});
        Map<Integer, Integer> data = new HashMap<Integer, Integer>();
        
        while(cursor.moveToNext()){
            data.put(cursor.getInt(0), cursor.getInt(1));
        }
        
        cursor.close();
        db.close();
        return data;
    }
    
    /**
     * 保存每条线程已经下载的文件长度
     * @param path
     * @param map
     */
    public void save(String path,  Map<Integer, Integer> map){//int threadid, int position
        SQLiteDatabase db = openHelper.getWritableDatabase();
        db.beginTransaction();
        
        try{
            for(Map.Entry<Integer, Integer> entry : map.entrySet()){
                db.execSQL("insert into filedownlog(downpath, threadid, downlength) values(?,?,?)",
                        new Object[]{path, entry.getKey(), entry.getValue()});
            }
            db.setTransactionSuccessful();
        }finally{
            db.endTransaction();
        }
        
        db.close();
    }
    
    /**
     * 实时更新每条线程已经下载的文件长度
     * @param path
     * @param map
     */
    public void update(String path, Map<Integer, Integer> map){
        SQLiteDatabase db = openHelper.getWritableDatabase();
        db.beginTransaction();
        
        try{
            for(Map.Entry<Integer, Integer> entry : map.entrySet()){
                db.execSQL("update filedownlog set downlength=? where downpath=? and threadid=?",
                        new Object[]{entry.getValue(), path, entry.getKey()});
            }
            
            db.setTransactionSuccessful();
        }finally{
            db.endTransaction();
        }
        
        db.close();
    }
    
    /**
     * 当文件下载完成后,删除对应的下载记录
     * @param path
     */
    public void delete(String path){
        SQLiteDatabase db = openHelper.getWritableDatabase();
        db.execSQL("delete from filedownlog where downpath=?", new Object[]{path});
        db.close();
    }

}  

 

DownloadProgressListener中代码:

 

package com.android.network;

public interface DownloadProgressListener {
    public void onDownloadSize(int size);

}  

FileDownloader中代码:

 

 

package com.android.network;

import java.io.File;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.android.service.FileService;

import android.content.Context;
import android.util.Log;

public class FileDownloader {
    private static final String TAG = "FileDownloader";
    private Context context;
    private FileService fileService;    
    
    /* 已下载文件长度 */
    private int downloadSize = 0;
    
    /* 原始文件长度 */
    private int fileSize = 0;
    
    /* 线程数 */
    private DownloadThread[] threads;
    
    /* 本地保存文件 */
    private File saveFile;
    
    /* 缓存各线程下载的长度*/
    private Map<Integer, Integer> data = new ConcurrentHashMap<Integer, Integer>();
    
    /* 每条线程下载的长度 */
    private int block;
    
    /* 下载路径  */
    private String downloadUrl;
    
    /**
     * 获取线程数
     */
    public int getThreadSize() {
        return threads.length;
    }
    
    /**
     * 获取文件大小
     * @return
     */
    public int getFileSize() {
        return fileSize;
    }
    
    /**
     * 累计已下载大小
     * @param size
     */
    protected synchronized void append(int size) {
        downloadSize += size;
    }
    
    /**
     * 更新指定线程最后下载的位置
     * @param threadId 线程id
     * @param pos 最后下载的位置
     */
    protected synchronized void update(int threadId, int pos) {
        this.data.put(threadId, pos);
        this.fileService.update(this.downloadUrl, this.data);
    }
    
    /**
     * 构建文件下载器
     * @param downloadUrl 下载路径
     * @param fileSaveDir 文件保存目录
     * @param threadNum 下载线程数
     */
    public FileDownloader(Context context, String downloadUrl, File fileSaveDir, int threadNum) {
        try {
            this.context = context;
            this.downloadUrl = downloadUrl;
            fileService = new FileService(this.context);
            URL url = new URL(this.downloadUrl);
            if(!fileSaveDir.exists()) fileSaveDir.mkdirs();
            this.threads = new DownloadThread[threadNum];                    
            
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setConnectTimeout(5*1000);
            conn.setRequestMethod("GET");
            conn.setRequestProperty("Accept", "image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/xaml+xml, application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*");
            conn.setRequestProperty("Accept-Language", "zh-CN");
            conn.setRequestProperty("Referer", downloadUrl); 
            conn.setRequestProperty("Charset", "UTF-8");
            conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)");
            conn.setRequestProperty("Connection", "Keep-Alive");
            conn.connect();
            printResponseHeader(conn);
            
            if (conn.getResponseCode()==200) {
                this.fileSize = conn.getContentLength();//根据响应获取文件大小
                if (this.fileSize <= 0) throw new RuntimeException("Unkown file size ");
                        
                String filename = getFileName(conn);//获取文件名称
                this.saveFile = new File(fileSaveDir, filename);//构建保存文件
                Map<Integer, Integer> logdata = fileService.getData(downloadUrl);//获取下载记录
                
                if(logdata.size()>0){//如果存在下载记录
                    for(Map.Entry<Integer, Integer> entry : logdata.entrySet())
                        data.put(entry.getKey(), entry.getValue());//把各条线程已经下载的数据长度放入data
                }
                
                if(this.data.size()==this.threads.length){//下面计算所有线程已经下载的数据长度
                    for (int i = 0; i < this.threads.length; i++) {
                        this.downloadSize += this.data.get(i+1);
                    }
                    
                    print("已经下载的长度"+ this.downloadSize);
                }
                
                //计算每条线程下载的数据长度
                this.block = (this.fileSize % this.threads.length)==0? this.fileSize / this.threads.length : this.fileSize / this.threads.length + 1;
            }else{
                throw new RuntimeException("server no response ");
            }
        } catch (Exception e) {
            print(e.toString());
            throw new RuntimeException("don‘t connection this url");
        }
    }
    
    /**
     * 获取文件名
     * @param conn
     * @return
     */
    private String getFileName(HttpURLConnection conn) {
        String filename = this.downloadUrl.substring(this.downloadUrl.lastIndexOf(‘/‘) + 1);
        
        if(filename==null || "".equals(filename.trim())){//如果获取不到文件名称
            for (int i = 0;; i++) {
                String mine = conn.getHeaderField(i);
                
                if (mine == null) break;
                
                if("content-disposition".equals(conn.getHeaderFieldKey(i).toLowerCase())){
                    Matcher m = Pattern.compile(".*filename=(.*)").matcher(mine.toLowerCase());
                    if(m.find()) return m.group(1);
                }
            }
            
            filename = UUID.randomUUID()+ ".tmp";//默认取一个文件名
        }
        
        return filename;
    }
    
    /**
     *  开始下载文件
     * @param listener 监听下载数量的变化,如果不需要了解实时下载的数量,可以设置为null
     * @return 已下载文件大小
     * @throws Exception
     */
    public int download(DownloadProgressListener listener) throws Exception{
        try {
            RandomAccessFile randOut = new RandomAccessFile(this.saveFile, "rw");
            if(this.fileSize>0) randOut.setLength(this.fileSize);
            randOut.close();
            URL url = new URL(this.downloadUrl);
            
            if(this.data.size() != this.threads.length){
                this.data.clear();
                
                for (int i = 0; i < this.threads.length; i++) {
                    this.data.put(i+1, 0);//初始化每条线程已经下载的数据长度为0
                }
            }
            
            for (int i = 0; i < this.threads.length; i++) {//开启线程进行下载
                int downLength = this.data.get(i+1);
                
                if(downLength < this.block && this.downloadSize<this.fileSize){//判断线程是否已经完成下载,否则继续下载    
                    this.threads[i] = new DownloadThread(this, url, this.saveFile, this.block, this.data.get(i+1), i+1);
                    this.threads[i].setPriority(7);
                    this.threads[i].start();
                }else{
                    this.threads[i] = null;
                }
            }
            
            this.fileService.save(this.downloadUrl, this.data);
            boolean notFinish = true;//下载未完成
            
            while (notFinish) {// 循环判断所有线程是否完成下载
                Thread.sleep(900);
                notFinish = false;//假定全部线程下载完成
                
                for (int i = 0; i < this.threads.length; i++){
                    if (this.threads[i] != null && !this.threads[i].isFinish()) {//如果发现线程未完成下载
                        notFinish = true;//设置标志为下载没有完成
                        
                        if(this.threads[i].getDownLength() == -1){//如果下载失败,再重新下载
                            this.threads[i] = new DownloadThread(this, url, this.saveFile, this.block, this.data.get(i+1), i+1);
                            this.threads[i].setPriority(7);
                            this.threads[i].start();
                        }
                    }
                }    
                
                if(listener!=null) listener.onDownloadSize(this.downloadSize);//通知目前已经下载完成的数据长度
            }
            
            fileService.delete(this.downloadUrl);
        } catch (Exception e) {
            print(e.toString());
            throw new Exception("file download fail");
        }
        return this.downloadSize;
    }
    
    /**
     * 获取Http响应头字段
     * @param http
     * @return
     */
    public static Map<String, String> getHttpResponseHeader(HttpURLConnection http) {
        Map<String, String> header = new LinkedHashMap<String, String>();
        
        for (int i = 0;; i++) {
            String mine = http.getHeaderField(i);
            if (mine == null) break;
            header.put(http.getHeaderFieldKey(i), mine);
        }
        
        return header;
    }
    
    /**
     * 打印Http头字段
     * @param http
     */
    public static void printResponseHeader(HttpURLConnection http){
        Map<String, String> header = getHttpResponseHeader(http);
        
        for(Map.Entry<String, String> entry : header.entrySet()){
            String key = entry.getKey()!=null ? entry.getKey()+ ":" : "";
            print(key+ entry.getValue());
        }
    }

    private static void print(String msg){
        Log.i(TAG, msg);
    }

 

DownloadThread 中代码:

 

 

package com.android.network;

import java.io.File;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;

import android.util.Log;

public class DownloadThread extends Thread {
    private static final String TAG = "DownloadThread";
    private File saveFile;
    private URL downUrl;
    private int block;
    
    /* 下载开始位置  */
    private int threadId = -1;    
    private int downLength;
    private boolean finish = false;
    private FileDownloader downloader;
    
    public DownloadThread(FileDownloader downloader, URL downUrl, File saveFile, int block, int downLength, int threadId) {
        this.downUrl = downUrl;
        this.saveFile = saveFile;
        this.block = block;
        this.downloader = downloader;
        this.threadId = threadId;
        this.downLength = downLength;
    }
    
    @Override
    public void run() {
        if(downLength < block){//未下载完成
            try {
                HttpURLConnection http = (HttpURLConnection) downUrl.openConnection();
                http.setConnectTimeout(5 * 1000);
                http.setRequestMethod("GET");
                http.setRequestProperty("Accept", "image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/xaml+xml, application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*");
                http.setRequestProperty("Accept-Language", "zh-CN");
                http.setRequestProperty("Referer", downUrl.toString()); 
                http.setRequestProperty("Charset", "UTF-8");
                int startPos = block * (threadId - 1) + downLength;//开始位置
                int endPos = block * threadId -1;//结束位置
                http.setRequestProperty("Range", "bytes=" + startPos + "-"+ endPos);//设置获取实体数据的范围
                http.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)");
                http.setRequestProperty("Connection", "Keep-Alive");
                
                InputStream inStream = http.getInputStream();
                byte[] buffer = new byte[1024];
                int offset = 0;
                print("Thread " + this.threadId + " start download from position "+ startPos);
                RandomAccessFile threadfile = new RandomAccessFile(this.saveFile, "rwd");
                threadfile.seek(startPos);
                
                while ((offset = inStream.read(buffer, 0, 1024)) != -1) {
                    threadfile.write(buffer, 0, offset);
                    downLength += offset;
                    downloader.update(this.threadId, downLength);
                    downloader.append(offset);
                }
                
                threadfile.close();
                inStream.close();
                print("Thread " + this.threadId + " download finish");
                this.finish = true;
            } catch (Exception e) {
                this.downLength = -1;
                print("Thread "+ this.threadId+ ":"+ e);
            }
        }
    }
    
    private static void print(String msg){
        Log.i(TAG, msg);
    }
    
    /**
     * 下载是否完成
     * @return
     */
    public boolean isFinish() {
        return finish;
    }
    
    /**
     * 已经下载的内容大小
     * @return 如果返回值为-1,代表下载失败
     */
    public long getDownLength() {
        return downLength;
    }

 

 

   运行效果如下:

 

 

 

版权声明:本文为博主原创文章,未经博主允许不得转载。

17Android手机操作系统已经出现就受到了用户的好评。各大手机厂商也开始利用这一开源的系统抓住商机,发展自己的产业。在这里先来了解一下这一操作系统的一个小技巧,有关Android显示网络图片的实现。

在Android中显示一张网络图片其实是超级简单的,下面就一个非常简单的例子:

Android显示网络图片Step1:

1、创建你的Activity,本例中以ViewWebImageActivity说明;

2、ViewWebImageActivity中的代码如下:

[java] view plaincopy

  1. String imageUrl = "http://hiphotos.baidu.com/baidu/pic  
  2. /item/7d8aebfebf3f9e125c6008d8.jpg";   
  3. //这就是你需要显示的网络图片---网上随便找的    
  4. Bitmap bmImg;     
  5. ImageView imView;    
  6. Button button1;     
  7. @Override     
  8. public void onCreate(Bundle savedInstanceState) {     
  9. super.onCreate(savedInstanceState);     
  10. setContentView(R.layout.main);     
  11. imView = (ImageView) findViewById(R.id.imview);     
  12. imView.setImageBitmap(returnBitMap(imageUrl));     
  13. }     
  14. public Bitmap returnBitMap(String url) {     
  15. URL myFileUrl = null;     
  16. Bitmap bitmap = null;     
  17. try {     
  18. myFileUrl = new URL(url);     
  19. } catch (MalformedURLException e) {     
  20. e.printStackTrace();     
  21. }     
  22. try {     
  23. HttpURLConnection conn = (HttpURLConnection)   
  24. myFileUrl.openConnection();     
  25. conn.setDoInput(true);     
  26. conn.connect();     
  27. InputStream is = conn.getInputStream();     
  28. bitmap = BitmapFactory.decodeStream(is);     
  29. is.close();     
  30. } catch (IOException e) {     
  31. e.printStackTrace();     
  32. }     
  33. return bitmap;     
  34. }  

 

3、其中,returnBitMap(String url) 方法就是具体实现网络图片转换成bitmap。

Android显示网络图片Step2:

1、修改你的main.xml文件如下:

[java] view plaincopy

  1. < ?xml version="1.0" encoding="utf-8"?>   
  2. < LinearLayout xmlns:android=  
  3. "http://schemas.android.com/apk/res/android"   
  4. android:orientation="vertical"   
  5. android:layout_width="fill_parent"   
  6. android:layout_height="fill_parent"   
  7. >   
  8. < ImageView     
  9. android:id="@+id/imview"   
  10. android:layout_width="wrap_content"     
  11. android:layout_height="wrap_content"     
  12. android:layout_gravity="center"     
  13. />     
  14. < /LinearLayout>   

 

Android显示网络图片Step3:

在你的AndroidManifest.xml文件的< /manifest>节点上面添加< uses-permission android:name="android.permission.INTERNET" />,这是由于Android有很多的权限限制,否则图片是不能在你的模拟器上显示的

18android

[java] view plaincopy

  1. <span style=" font-family: Arial, Tahoma, Verdana, sans-serif; font-size: 14px;">获取网络信息需要在AndroidManifest.xml文件中加入相应的权限。 </span>  

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> 

1)判断是否有网络连接 

[java] view plaincopy

  1. public boolean isNetworkConnected(Context context) {   
  2. if (context != null) {   
  3. ConnectivityManager mConnectivityManager = (ConnectivityManager) context   
  4. .getSystemService(Context.CONNECTIVITY_SERVICE);   
  5. NetworkInfo mNetworkInfo = mConnectivityManager.getActiveNetworkInfo();   
  6. if (mNetworkInfo != null) {   
  7. return mNetworkInfo.isAvailable();   
  8. }   
  9. }   
  10. return false;   
  11. }   

 

2)判断WIFI网络是否可用 

[java] view plaincopy

  1. public boolean isWifiConnected(Context context) {   
  2. if (context != null) {   
  3. ConnectivityManager mConnectivityManager = (ConnectivityManager) context   
  4. .getSystemService(Context.CONNECTIVITY_SERVICE);   
  5. NetworkInfo mWiFiNetworkInfo = mConnectivityManager   
  6. .getNetworkInfo(ConnectivityManager.TYPE_WIFI);   
  7. if (mWiFiNetworkInfo != null) {   
  8. return mWiFiNetworkInfo.isAvailable();   
  9. }   
  10. }   
  11. return false;   
  12. }   

 

3)判断MOBILE网络是否可用 

[java] view plaincopy

  1. public boolean isMobileConnected(Context context) {   
  2. if (context != null) {   
  3. ConnectivityManager mConnectivityManager = (ConnectivityManager) context   
  4. .getSystemService(Context.CONNECTIVITY_SERVICE);   
  5. NetworkInfo mMobileNetworkInfo = mConnectivityManager   
  6. .getNetworkInfo(ConnectivityManager.TYPE_MOBILE);   
  7. if (mMobileNetworkInfo != null) {   
  8. return mMobileNetworkInfo.isAvailable();   
  9. }   
  10. }   
  11. return false;   
  12. }   

 

4)获取当前网络连接的类型信息 

[java] view plaincopy

  1. public static int getConnectedType(Context context) {   
  2. if (context != null) {   
  3. ConnectivityManager mConnectivityManager = (ConnectivityManager) context   
  4. .getSystemService(Context.CONNECTIVITY_SERVICE);   
  5. NetworkInfo mNetworkInfo = mConnectivityManager.getActiveNetworkInfo();   
  6. if (mNetworkInfo != null && mNetworkInfo.isAvailable()) {   
  7. return mNetworkInfo.getType();   
  8. }   
  9. }   
  10. return -1;   
  11. }   

 

在开发android应用时,涉及到要进行网络访问,时常需要进行网络状态的检查,以提供给用户必要的提醒。一般可以通过ConnectivityManager来完成该工作。 

ConnectivityManager有四个主要任务 
1、监听手机网络状态(包括GPRSWIFI, UMTS
2、手机状态发生改变时,发送广播 
3、当一个网络连接失败时进行故障切换 
4、为应用程序提供可以获取可用网络的高精度和粗糙的状态 
当我们要在程序中监听网络状态时,只要一下几个步骤即可: 

1、定义一个Receiver重载其中的onReceive函数,在其中完成所需要的功能,如根据WIFIGPRS是否断开来改变空间的外观 

[java] view plaincopy

  1. connectionReceiver = new BroadcastReceiver() {   
  2. @Override   
  3. public void onReceive(Context context, Intent intent) {   
  4. ConnectivityManager connectMgr = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);   
  5. NetworkInfo mobNetInfo = connectMgr.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);   
  6. NetworkInfo wifiNetInfo = connectMgr.getNetworkInfo(ConnectivityManager.TYPE_WIFI);   
  7. if (!mobNetInfo.isConnected() && !wifiNetInfo.isConnected()) {   
  8. Log.i(TAG, "unconnect");   
  9. // unconnect network   
  10. }else {   
  11. // connect network   
  12. }   
  13. }   
  14. };   

 

2、在适当的地方注册Receiver,可以在程序中注册,在onCreate中调用如下函数即可: 

[java] view plaincopy

  1. IntentFilter intentFilter = new IntentFilter();   
  2. intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);   
  3. registerReceiver(connectionReceiver, intentFilter);   



3、在适当时取消注册Receiver,可以在程序中取消,在onDestroye中调用如下函数即可: 

[java] view plaincopy

  1. if (connectionReceiver != null) {   
  2. unregisterReceiver(connectionReceiver);   
  3. }   

 

Ps:网上还有很多关于使用TelephonyManager 的方法的,方法如下(但是我试了好几次都有问题,如每次第一次进入一个Activity时会自动收到网络断开的信号,每次网络状态改变时收到多次回调且状态不正确。不知道有什么要注意的地方,求指点!) 

[java] view plaincopy

  1. final TelephonyManager mTelephonyMgr = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);   
  2. mTelephonyMgr.listen(new PhoneStateListener(){   
  3. @Override   
  4. public void onDataConnectionStateChanged(int state) {   
  5. switch(state){   
  6. case TelephonyManager.DATA_DISCONNECTED://网络断开   
  7. break;   
  8. case TelephonyManager.DATA_CONNECTING://网络正在连接   
  9. break;   
  10. case TelephonyManager.DATA_CONNECTED://网络连接上   
  11. break;   
  12. }   
  13. }   
  14. }, PhoneStateListener.LISTEN_DATA_CONNECTION_STATE);   

 

至于第二种方法,本人并没有去尝试过。第一种方式还是比较好用,如果要程序隐藏在后台的话,建议开个service,将BroadcastReceiver注册在service,但不要忘了取消注册。 

在测试中遇到过这样的状况,将一个当前连接wifi的路由设备关闭,但是程序并没有捕捉到unconnect network,可能是因为手机设备立刻连接另一个路由设备了 

Android 监控网络状态 

[java] view plaincopy

  1. public static boolean isNetworkAvailable(Context context) {   
  2. ConnectivityManager connectivity = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);   
  3. if (connectivity == null) {   
  4. Log.i("NetWorkState", "Unavailabel");   
  5. return false;   
  6. } else {   
  7. NetworkInfo[] info = connectivity.getAllNetworkInfo();   
  8. if (info != null) {   
  9. for (int i = 0; i < info.length; i++) {   
  10. if (info[i].getState() == NetworkInfo.State.CONNECTED) {   
  11. Log.i("NetWorkState", "Availabel");   
  12. return true;   
  13. }   
  14. }   
  15. }   
  16. }   
  17. return false;   
  18. }   

 

上面这个方法就是判断网络是否连接的代码,返回true表示有网络,返回false表示无网络。 在Android网络应用程序开发中,经常要判断网络连接是否可用,因此经常有必要监听网络状态的变化。android的网络状态监听可以用BroadcastReceiver来接收网络状态改变的广 播,具体实现如下 

[java] view plaincopy

  1. @Override   
  2. public void onReceive(Context context, Intent intent) {   
  3. Log.e(TAG, "网络状态改变");   
  4. boolean success = false;   
  5. //获得网络连接服务   
  6. ConnectivityManager connManager = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);   
  7. // State state = connManager.getActiveNetworkInfo().getState();   
  8. State state = connManager.getNetworkInfo(   
  9. ConnectivityManager.TYPE_WIFI).getState(); // 获取网络连接状态   
  10. if (State.CONNECTED == state) { // 判断是否正在使用WIFI网络   
  11. success = true;   
  12. }   
  13. state = connManager.getNetworkInfo(   
  14. ConnectivityManager.TYPE_MOBILE).getState(); // 获取网络连接状态   
  15. if (State.CONNECTED != state) { // 判断是否正在使用GPRS网络   
  16. success = true;   
  17. }   
  18. if (!success) {   
  19. Toast.makeText(LocationMapActivity.this, "您的网络连接已中断", Toast.LENGTH_LONG).show();   
  20. }   
  21. }   

 

[java] view plaincopy

  1. //注册网络监听   
  2. IntentFilter filter = new IntentFilter();   
  3. filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);   
  4. registerReceiver(mNetworkStateReceiver, filter);   
  5. //在Activity中的onDestroy中:‘   
  6. unregisterReceiver(mNetworkStateReceiver); //取消监听   


很多朋友在android开发中,都会遇到手机网络类型判断,因为就目前的android平台手机来说:可能会存在4中状态 

1.无网络(这种状态可能是因为手机停机,网络没有开启,信号不好等原因) 
2.使用WIFI上网 
3.CMWAP(中国移动代理) 
4.CMNET上网 
这四种状态,如果没有网络,肯定是无法请求Internet了,如果是wap就需要为手机添加中国移动代理,关于为手机添加中国移动的代理! 

下面是网络判断的方法: 

[java] view plaincopy

  1. /**  
  2. * @author sky  
  3. * Email vipa1888@163.com  
  4. * QQ:840950105  
  5. * 获取当前的网络状态 -1:没有网络 1:WIFI网络2:wap网络3:net网络  
  6. * @param context  
  7. * @return  
  8. */   
  9. public static int getAPNType(Context context){   
  10. int netType = -1;   
  11. ConnectivityManager connMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);   
  12. NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();   
  13. if(networkInfo==null){   
  14. return netType;   
  15. }   
  16. int nType = networkInfo.getType();   
  17. if(nType==ConnectivityManager.TYPE_MOBILE){   
  18. Log.e("networkInfo.getExtraInfo()", "networkInfo.getExtraInfo() is "+networkInfo.getExtraInfo());   
  19. if(networkInfo.getExtraInfo().toLowerCase().equals("cmnet")){   
  20. netType = CMNET;   
  21. }   
  22. else{   
  23. netType = CMWAP;   
  24. }   
  25. }   
  26. else if(nType==ConnectivityManager.TYPE_WIFI){   
  27. netType = WIFI;   
  28. }   
  29. return netType;   
  30. }   

 

 

6、android 网络编程

标签:

原文地址:http://www.cnblogs.com/evertriely/p/4625717.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!