在基于Android的APP开发中,不只是单一的在手机上操作,而是通常我们会和网络进行连接,把数据通过网络传输到服务器上,或者从服务器上拿到数据在APP上显示,也就是与服务器进行交互,前提是通过网络。我在做项目的时候完成了一些简单的与服务器之间的交互,在此给大家写出,互相学习。

     所有的数据传输都是基于HTTP协议的,不是通过TCP协议。

     Android中有两种自带的访问网络的API  1 URLConnection方法 2 HttpClient方法;在向服务器传输数据时,又有两种方式get方式和post方式。每一种方法每一种方式,我都采用函数的方法写出。

    1 URLConnection 方法采用 get方式

<span ><span >public static String getmethod(String username,String password) throws IOException 
	{
		//提交数据到服务器,采用get方式
		//拼装路径
		//String  path = "http://192.168.0.105:8080/StructsDemo/hello?hhh=";
		//对于网络请求,最好弄成线程
		String path ="http://192.168.0.105:8080/StructsDemo/hello?username="+URLEncoder.encode(username,"gbk")+"&password="+URLEncoder.encode(password,"gbk");
		URL url = new URL(path);
		HttpURLConnection conn = (HttpURLConnection) url.openConnection();
		conn.setReadTimeout(5000);                       //读取的时间
		conn.setRequestMethod("GET");
		int code = conn.getResponseCode();    //获得服务器的响应
		if(code == 200)
		{
			   InputStream is = conn.getInputStream();
			   String text;
			   text = StreamTools.readInputStream1(is);
			   return text;
			   
		}
		else
			return null;
	  }</span></span>

get方式需要采用拼装字符串的方法,获得网址,在网址后添加要传输的值(username,password),通过android自带的API,采用URLConnection方法与Web进行连接,然后向服务器发送数据。获得服务器的响应,如果code = 200 就说明连接成功,这时候我们定义IuputStream来获取从服务器上的数据(只要服务器发送了消息,我们就能用InputStream获得服务器的消息),不同设备之间的数据交互,通常都是已字节流的形式传输,这个时候InputStream里面就有服务器发送的数据了,只不过是以流的形式存在,所有我们需要转化形式。用如下函数:

<span ><span >           public static String readInputStream1(InputStream is)
		{ 
			 ByteArrayOutputStream baos = new ByteArrayOutputStream(); //可以捕获内存缓冲区中的数据,然后转化成字节数组
			 int len = 0;
			 byte[] buffer = new byte[1024];
			 
			    try {
					while ((len = is.read(buffer))!=-1)
					{
						baos.write(buffer, 0, len);//把buffer中的内容从0写到len
					}
					is.close();
					baos.close();
					byte[] result = baos.toByteArray();
					return new String(result);
				} 
			    catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
					return null;
				}
		}

</span></span>

这个函数是把字节流转化为字符串,这样就能看到服务器发送的数据了。

 2 URLConnection 方法采用 post方式

<span ><span >public static String postmethod(String username,String password) throws IOException 
	{
		//提交数据到服务器,采用post方式
		//拼装路径
		//String  path = "http://192.168.0.105:8080/StructsDemo/hello?hhh=";
		//对于网络请求,最好弄成线程
		String path ="http://192.168.0.105:8080/StructsDemo/hello";
		URL url = new URL(path);
		HttpURLConnection conn = (HttpURLConnection) url.openConnection();
		conn.setReadTimeout(5000);
		conn.setRequestMethod("POST");
		//准备 数据
		String data= "username="+username+"password="+password;
		// 设置请求的头  
       // conn.setRequestProperty("Connection", "keep-alive");  
        // 设置请求的头  
        conn.setRequestProperty("Content-Type",  
                "application/x-www-form-urlencoded");  
        // 设置请求的头  
        conn.setRequestProperty("Content-Length",  
                String.valueOf(data.length()+""));  
        // 设置请求的头  
     //   conn.setRequestProperty("User-Agent",  
                  //      "Mozilla/5.0 (Windows NT 6.3; WOW64; rv:27.0) Gecko/20100101 Firefox/27.0");
		//post的方式其实是浏览器把数据写给服务器
		conn.setDoOutput(true);    //允许向外写数据
		conn.setDoInput(true);     //允许向内读数据
		OutputStream os = conn.getOutputStream();   //获得输出流,可以用输出流向服务器写内荣
		os.write(data.getBytes());                  //把内容写到服务器
		
		
		int code = conn.getResponseCode();           //获得服务器的响应
		if(code == 200)
		{
			   InputStream is = conn.getInputStream();
			   String text;
			   text = StreamTools.readInputStream1(is);
			   return text;
			   
		}
		else
			return null;
	  }</span></span>

具体细节可以看代码。

 3  HttpClient 方法采用 get 方式 (HttpClient API 在 SDK 5.0 以后就被弃用了,也就是代码上画横线)   

<span ><span >/**
	 * 采用httpclient 的get方式访问服务器
	 * @param username
	 * @param password
	 * @return
	 * @throws IOException 
	 * @throws  
	 */
	public static String LoginByClientget(String username,String password) throws  IOException  
	{    
		 //打开一个浏览器
		 HttpClient client = new DefaultHttpClient();  //一个接口 (每个接口都有实现类)
		 //输入地址
		 String path ="http://192.168.0.105:8080/StructsDemo/hello?username="+username+"&password="+password;
		 HttpGet httpget = new HttpGet(path);
		 //敲回车
		 HttpResponse response = client.execute(httpget);           //获得服务器返回的信息
		 int code ;
		 code = response.getStatusLine().getStatusCode();          //得到状态行状态码
		 if(code == 200)
			{
				   InputStream is = response.getEntity().getContent();  //获得服务器返回来的流
				   String text;
				   text = StreamTools.readInputStream1(is);
				   return text;	   
			}
			else
				return null;
     }</span></span>

代码上都有注释,在此就不讲了。

 4 HttpClient方法采用post方式(HttpClient API 在 SDK 5.0 以后就被弃用了,也就是代码上画横线)

<span ><span >public static String LoginByClientpost(String username,String password) throws  IOException  
	{    
		 //打开一个浏览器
		 HttpClient client = new DefaultHttpClient();  //一个接口 (每个接口都有实现类)
		 //输入地址
		 String path ="http://192.168.0.105:8080/StructsDemo/hello";
		 HttpPost httppost = new HttpPost(path);    
		 //指定要提交的数据实体(以表单的形式)   NameValuePair  键指対 是一个借口,要使用接口类型可以使用类
		 List<NameValuePair> parameters = new ArrayList<NameValuePair>();
		 parameters.add(new BasicNameValuePair("username", username));
		 parameters.add(new BasicNameValuePair("password", password));
		 httppost.setEntity(new UrlEncodedFormEntity(parameters, "gbk") );
	     //敲回车
		HttpResponse response =  client.execute(httppost);
		int code ;
		 code = response.getStatusLine().getStatusCode();          //得到状态行状态码
		 if(code == 200)
			{
				   InputStream is = response.getEntity().getContent();  //获得服务器返回来的流
				   String text;
				   text = StreamTools.readInputStream1(is);
				   return text;
				   
			}
			else
				return null;
	}</span></span>

以上方法为Android系统自带的API,可以实现与服务器的交互。为了方便起见,我们还可以使用开源的代码包来实现这些功能,非常方便,高手已经封装好了,你直接用就行。

 5  异步框架AsyncHttpClient,加入别人写好的包,直接调用包中的AsyncHttpClient框架,采用post方式 

<span ><span >            //传输json字符串采用AsyncHttpClient异步框架
			 AsyncHttpClient client1  = new AsyncHttpClient();
			 String path1 = "http://219.244.48.159:8080/WeChat/registerSmartDogAction.action";
			 RequestParams params  = new RequestParams();
			 params.add("register", msg);
			 client1.post(path1, params,  new AsyncHttpResponseHandler(){

				@Override
				public void onSuccess(int statusCode, Header[] headers,
						byte[] responseBody) {
					// TODO Auto-generated method stub
					//String returninfo = responseBody.toString();
				//	String  jiequinfo = returninfo.substring(0,3);
					
					Toast.makeText(register.this,new String(responseBody).substring(8, 12) , 0).show();
					
				}
              //responsBody 是服务器返回的内容
				@Override
				public void onFailure(int statusCode, Header[] headers,
						byte[] responseBody, Throwable error) {
					// TODO Auto-generated method stub
					Toast.makeText(register.this, new String(responseBody), 0).show();
				}
				}) ;</span></span>

由以上代码可以看出,在进行网络数据交互的时候非常方便, 1 new 一个 AsyncHttpClient 对象,2 写一个地址,3 new  一个 RequestParams 对象 4 用RequestParams 装载数据,以键值对的方式 5 用AsyncHttpClient的对象,post数据(路径,装载的数据, new AsyncHttpResponseHandler(){

                             作用是处理服务器返回的数据

                              public  void     onSuccess(){

                               服务器连接成功,返回的数据                  

 }

                              public  void  onFailure(){

                             服务器连接失败,返回的数据

 }

});

AsyncHttpClient框架代码地址:

下载好之后解压缩,把com文件整个放到工程的src文件夹下,当一个包引入,最简便方法粘贴复制。

6  上述方法都是向服务器请求数据(只是字符串),如果想要通过http协议向服务器请求图片,或者视频,音频的话(通常都使用的是POST方式),其它的操作都一样,只要改变一下请求资源的地址,然后使用post方式就行了,举例:

String path = "http://192.168.0.135:8080/jsonweb/WebRoot/pitcures/bb.jpg";
    	   HttpClient client = new DefaultHttpClient();
    	   HttpGet   get  =  new HttpGet(path);
    	   HttpResponse  response =client.execute(get);
    	   int code ;
    	   code = response.getStatusLine().getStatusCode();    
    	   if(code == 200)
    	   {
    		   InputStream is = response.getEntity().getContent();
    		   Bitmap bitmap = BitmapFactory.decodeStream(is);
    		   return bitmap;
    		   
    	   }

上述代码就是用HttpClient的方法的post方式向服务器请求图片,如果code==200,服务器就会返回图片的字节流,通常这时候处理字节流有上述代码使用的方法,采用BitmapFactory.decodeStream函数,这个相当于在线看,没有下载下来;还有最普遍的方法写文件方法这个相当于下载下来(不管是音频文件,视频文件,图片文件,只要是文件转化的字节流都可以使用这种方法):

File file  = new File("自己客户端想要存储的位置");
    	   FileOutputStream output = new FileOutputStream(file);
    	   byte [] byte1 = new byte[1024];
    	   int length = 0 ;
    	   while( (length = (is.read(byte1))!= -1){
    		   output.write(byte1,0,length);
    	   }
    	   output.close();

这样就把这个向服务器请求的图片下载到了你想要保存的地方。

7  如果想要通过客户端向服务器端上传文件应该怎么办,在这里我只使用AsyncHttpClient开源库举例子:代码很简单

String path = address.getText().toString().trim(); //要上传文件的位置
			 String address1 = "http://192.168.0.105:8080/StructsDemo/upload";
			final File file = new File(path);
			 if(file.exists()&& file.length()>0)
			 {
				 AsyncHttpClient client  = new AsyncHttpClient();
				 RequestParams params = new RequestParams();
				 try {
					params.put("profile-picture", file);
					client.post(address1, params, new AsyncHttpResponseHandler() {   //上传文件到服务器端
						
						@Override
						public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
							// TODO Auto-generated method stub
							Toast.makeText(MainActivity.this,"请求成功",0).show();
						}
						
						@Override
						public void onFailure(int statusCode, Header[] headers,
								byte[] responseBody, Throwable error) {
							// TODO Auto-generated method stub
							Toast.makeText(MainActivity.this,"请求失败",0).show();
						}
					}) ;

服务器端的upload.jsp网页上的代码:

<form action="up" method="post" enctype="multipart/form-data">
           选择的文件:<input name="uploadFile" type="file">
           </br>
      <input name="submit" type="submit" value="上传">     
   
   
   </form>

enctype必须写成“mutipart/form-data”, params中的属性必须写成“profile-picture”

服务器端后台代码为:

public class upload  extends ActionSupport{
	   
	    private File uploadFile;          // 得到上传的文件,此属性对应于表单中文件字段的名称  
	                                      //下面的这两个属性的命名必须遵守上定的规则,即为"表单中文件字段的名称" + "相应的后缀"  
	    private String uploadFileContentType; // 得到上传的文件的数据类型,  
	    private String uploadFileFileName; // 得到上传的文件的名称  
	  
	    public File getUploadFile() {  
	        return uploadFile;  
	    }  
	  
	    public void setUploadFile(File uploadFile) {  
	        this.uploadFile = uploadFile;  
	    }  
	  
	    public String getUploadFileContentType() {  
	        return uploadFileContentType;  
	    }  
	  
	    public void setUploadFileContentType(String uploadFileContentType) {  
	        this.uploadFileContentType = uploadFileContentType;  
	    }  
	  
	    public String getUploadFileFileName() {  
	        return uploadFileFileName;  
	    }  
	  
	    public void setUploadFileFileName(String uploadFileFileName) {  
	        this.uploadFileFileName = uploadFileFileName;  
	    }  
	
	    public String execute() throws Exception {  
	        String realPath = ServletActionContext.getServletContext().getRealPath("/images");  
	        System.out.println(realPath);  
	        if(uploadFile !=null ){  
	            File destFile = new File(new File(realPath), uploadFileFileName);//根据 parent 抽象路径名和 child 路径名字符串创建一个新 File 实例。  
	            if(!destFile.getParentFile().exists())//判断路径"/images"是否存在  
	                destFile.getParentFile().mkdirs();//如果不存在,则创建此路径  
	            //将文件保存到硬盘上,因为action运行结束后,临时文件就会自动被删除  
	            FileUtils.copyFile(uploadFile, destFile);  
	            ActionContext.getContext().put("message", "文件上传成功!");  
	        }  
	        return "success";  
	    }  
	
}

注:服务器端的后台代码能够继承ActionSupport类因为采用的是Structs框架