6、android 网络编程

时间:2023-11-22 17:20:08

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的情况下需要设置DoOutput为true

    urlConn.setRequestMethod("POST");

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

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

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

    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. @Override
  32. public void onClick(View v) {
  33. String strPhone=phone.getText().toString().trim();
  34. if(!(strPhone.length()==0||strPhone.equals("")))
  35. {
  36. String str = "";
  37. try {
  38. str = getPhoneInfo(strPhone);
  39. } catch (IOException e) {
  40. // TODO Auto-generated catch block
  41. e.printStackTrace();
  42. } catch (XmlPullParserException e) {
  43. // TODO Auto-generated catch block
  44. e.printStackTrace();
  45. }
  46. result.setText(str);
  47. }
  48. }
  49. });
  50. }
  51. public String getPhoneInfo(String phoneName) throws IOException, XmlPullParserException
  52. {
  53. //返回的查询结果
  54. String result = null;
  55. //调用webservice接口的名称空间
  56. String nameSpace="http://WebXml.com.cn/";
  57. //调用的方法名
  58. String methodName="getMobileCodeInfo";
  59. //将方法名和名称空间绑定在一起
  60. String SOAP_ACTION = nameSpace + methodName;
  61. //获得返回请求对象
  62. SoapObject request = new SoapObject(nameSpace, methodName);
  63. //设置需要返回请求对象的参数
  64. request.addProperty("mobileCode", phoneName);
  65. request.addProperty("userId", "");
  66. //设置soap的版本
  67. SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
  68. SoapEnvelope.VER11);
  69. //设置是否调用的是dotNet开发的
  70. envelope.dotNet = true;
  71. //
  72. envelope.bodyOut = request;
  73. AndroidHttpTransport hts = new AndroidHttpTransport
  74. ("http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx");
  75. // web service请求
  76. hts.call(SOAP_ACTION, envelope);
  77. // 得到返回结果
  78. Object o = envelope.getResponse();
  79. result = o.toString();
  80. return result;
  81. }
  82. }

6、一、获取并使用KSOAP包

在Android SDK中并没有提供调用WebService的库,因此,需要使用第三方的SDK来调用WebService。PC版本的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. }

10、Android开发应用程序时,如果应用程序需要访问网络权限,需要在 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

允许一个程序访问CellID或WiFi热点来获取粗略的位置(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系统自动获取最符合Criteria的LocationProvider,从而实现了定位功能。这样的做法能最大限度的保证定位功能的可实现性,但是却无法保证获取到的位置信息有最大的准确度。因为除了GPS外,其他定位方式都或多或少存在着位置偏移。

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

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

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

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

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

1、获取GPS的Location 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. });

15、Android  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. *
  31. * This method is called when a form has its tag value method equals to get.
  32. *
  33. * @param request the request send by the client to the server
  34. * @param response the response send by the server to the client
  35. * @throws ServletException if an error occurred
  36. * @throws IOException if an error occurred
  37. */
  38. public void doGet(HttpServletRequest request, HttpServletResponse response)
  39. throws ServletException, IOException {
  40. doPost(request, response);
  41. }
  42. /**
  43. * The doPost method of the servlet. <br>
  44. *
  45. * This method is called when a form has its tag value method equals to post.
  46. *
  47. * @param request the request send by the client to the server
  48. * @param response the response send by the server to the client
  49. * @throws ServletException if an error occurred
  50. * @throws IOException if an error occurred
  51. */
  52. public void doPost(HttpServletRequest request, HttpServletResponse response)
  53. throws ServletException, IOException {
  54. response.setContentType("text/html");
  55. PrintWriter out = response.getWriter();
  56. List<User> list = new ArrayList<User>();
  57. User u1 = new User();
  58. u1.setId(111);
  59. u1.setUsername("zhang shan");
  60. u1.setPassword("zs");
  61. User u2 = new User();
  62. u2.setId(222);
  63. u2.setUsername("li si");
  64. u2.setPassword("ls");
  65. User u3 = new User();
  66. u3.setId(333);
  67. u3.setUsername("wang wu");
  68. u3.setPassword("ww");
  69. list.add(u1);
  70. list.add(u2);
  71. list.add(u3);
  72. JSONArray ja = new JSONArray();
  73. for (Iterator iterator = list.iterator(); iterator.hasNext();) {
  74. User user = (User) iterator.next();
  75. JSONObject jobj= new JSONObject();
  76. jobj.put("id", user.getId());
  77. jobj.put("username", user.getUsername());
  78. jobj.put("password", user.getPassword());
  79. ja.add(jobj);
  80. }
  81. out.write(ja.toString());
  82. out.flush();
  83. out.close();
  84. }
  85. /**
  86. * Initialization of the servlet. <br>
  87. *
  88. * @throws ServletException if an error occurs
  89. */
  90. public void init() throws ServletException {
  91. // Put your code here
  92. }
  93. }

[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、我们编写的是Andorid的HTTP协议多线程断点下载应用程序。直接使用单线程下载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) ,第1,2个线程下载长度是4M,第三个线程下载长度为2M

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

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

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

如:指定从文件的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;
    }

}

运行效果如下:

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

17、Android手机操作系统已经出现就受到了用户的好评。各大手机厂商也开始利用这一开源的系统抓住商机,发展自己的产业。在这里先来了解一下这一操作系统的一个小技巧,有关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有很多的权限限制,否则图片是不能在你的模拟器上显示的

18、android

[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、监听手机网络状态(包括GPRS,WIFI, UMTS等) 
2、手机状态发生改变时,发送广播 
3、当一个网络连接失败时进行故障切换 
4、为应用程序提供可以获取可用网络的高精度和粗糙的状态 
当我们要在程序中监听网络状态时,只要一下几个步骤即可:

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

[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. }