Android 与远程服务器交互

一、远程服务器存储

1、说明

(1对于联网的APP来说, 可能需要通过请求向服务器提交请求数据, 也可能需要从服务器端获取数据显示

(2如何编码实现客户端与服务器端的交互呢? 

JDK内置的原生API :HttpUrlConnection

Android内置的包装API:HttpClient    浏览器  

异步网络请求框架:Volley,Xutils

(3注意:

访问网络, 需要声明权限: android.permission.INTERNET

访问网络的程序必须在分线程执行

 

2、HTTP协议(复习)

• 一次HTTP请求的过程    

– 建立连接-à发送请求-à处理请求-à返回数据-à发送请求2-à………关闭连接 

• HTTP请求的常用方式 

– GET

– POST

• HTTP请求的格式 

– 请求行 

– 请求头 

– 请求体 

• HTTP响应的格式 

– 响应行 

– 响应头 

– 响应体 

 

二、使用HttpConnection

1.URL : 包含请求地址的类 

URL(path) : 包含请求路径的构造方法 

openConnection() : 得到连接对象 

 

2.HttpURLConnection : 代表与服务器连接的类 

setMethod(“GET/POST”) : 设置请求方式 

setConnectTimeout(time) : 设置连接超时时间, 单位为ms

setReadTimeout(time): 设置读取服务器返回数据的时间 

connect() : 连接服务器 

int getResponseCode(): 得到服务器返回的结果码 

Int getContentLength() : 得到服务器返回数据的长度(字节)

getOutputStream() : 返回一个指向服务器端的数据输出流 

getInputStream() : 返回一个从服务器端返回的数据输入流 

disconnect() : 断开连接

权限:

 <!-- 联网 --> <uses-permission android:name="android.permission.INTERNET"/>
public class MainActivity extends Activity {

    private EditText et_main_message;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        et_main_message=findViewById(R.id.et_main_message);
    }

    /*
    * 使用httpUrlConnection提交get请求
    */
   /*
      1. 显示ProgressDialog
      2. 启动分线程
      3. 在分线程, 发送请求, 得到响应数据
         1). 得到path, 并带上参数name=Tom1&age=11
         2). 创建URL对象
         3). 打开连接, 得到HttpURLConnection对象
         4). 设置请求方式,连接超时, 读取数据超时
         5). 连接服务器
         6). 发请求, 得到响应数据
            得到响应码, 必须是200才读取
            得到InputStream, 并读取成String
         7). 断开连接
      4. 在主线程, 显示得到的结果, 移除dialog
    */
    public void get(View v){
        //1. 显示ProgressDialog
        final ProgressDialog progressDiag= ProgressDialog.show(this,null,"正在请求中");
        //2. 启动分线程
        new Thread(){
            //3. 在分线程, 发送请求, 得到响应数据
            public void run(){

                try {
                    //1). 得到path, 并带上参数
                    String path="http://192.168.0.118/test.php?id=2";
                    //2). 创建URL对象
                    URL url=new URL(path);
                    //3). 打开连接, 得到HttpURLConnection对象
                    HttpURLConnection connection=(HttpURLConnection)url.openConnection();
                    //4). 设置请求方式,连接超时, 读取数据超时
                    connection.setRequestMethod("GET");
                    connection.setConnectTimeout(200);
                    connection.setReadTimeout(200);
                    //5). 连接服务器
                    connection.connect();
                    //6). 发请求, 得到响应数据
                    //得到响应码, 必须是200才读取
                    int code=connection.getResponseCode();
                    if(code==200){
                        //得到InputStream, 并读取成String
                        InputStream is=connection.getInputStream();
                        ByteArrayOutputStream bao=new ByteArrayOutputStream();
                        byte[] flush=new byte[1024];
                        int len=1;
                        while((len=is.read(flush))!=-1){
                            bao.write(flush,0,len);
                        }
                        final String result=bao.toString();
                        bao.close();
                        is.close();

                        //4. 在主线程, 显示得到的结果, 移除dialogs
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                et_main_message.setText(result);
                                progressDiag.dismiss();
                            }
                        });
                    }


                    //7). 断开连接
                    connection.disconnect();
                } catch (MalformedURLException e) {
                    e.printStackTrace();
                    //如果出了异常要移除dialog
                    progressDiag.dismiss();
                } catch (IOException e) {
                    e.printStackTrace();
                    //如果出了异常要移除dialog
                    progressDiag.dismiss();
                }
            }

        }.start();


    }

    /*
    * 使用httpUrlConnection提交post请求
    */
   /*
      1. 显示ProgressDialog
      2. 启动分线程
      3. 在分线程, 发送请求, 得到响应数据
         1). 得到path
         2). 创建URL对象
         3). 打开连接, 得到HttpURLConnection对象
         4). 设置请求方式,连接超时, 读取数据超时
         5). 连接服务器
         6). 发请求, 得到响应数据
            得到输出流, 写请求体:name=Tom1&age=11
            得到响应码, 必须是200才读取
            得到InputStream, 并读取成String
         7). 断开连接
      4. 在主线程, 显示得到的结果, 移除dialog
    */
    public void post(View v){
        //1. 显示ProgressDialog
        final ProgressDialog progressDialog=ProgressDialog.show(this,null,"正在加载数据");
        //2. 启动分线程
        new Thread(new Runnable() {
            //3. 在分线程, 发送请求, 得到响应数据
            @Override
            public void run() {
                try {
                    //1). 得到path
                    String path="http://192.168.0.118/test.php";
                    //2). 创建URL对象
                    URL url=new URL(path);
                    //3). 打开连接, 得到HttpURLConnection对象
                    HttpURLConnection connection=(HttpURLConnection)url.openConnection();
                    //4). 设置请求方式,连接超时, 读取数据超时
                    connection.setRequestMethod("POST");
                    connection.setConnectTimeout(2000);
                    connection.setReadTimeout(5000);
                    //5). 连接服务器
                    connection.connect();
                    //6). 发请求, 得到响应数据
                    //得到输出流, 写请求体:name=Tom1&age=11
                    OutputStream os=connection.getOutputStream();
                    String data="id=2&name=haitao";
                    os.write(data.getBytes("utf-8"));
                    //得到响应码, 必须是200才读取
                    int code=connection.getResponseCode();
                    if(code==200){
                        //得到InputStream, 并读取成String
                        InputStream is=connection.getInputStream();
                        ByteArrayOutputStream bao=new ByteArrayOutputStream();
                        byte[] flush=new byte[1024];
                        int len=-1;
                        while( (len=is.read(flush))!=-1 ){
                            bao.write(flush,0,len);
                        }
                        final String result=bao.toString();
                        bao.close();
                        is.close();
                        //4. 在主线程, 显示得到的结果, 移除dialog
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                et_main_message.setText(result);
                                progressDialog.dismiss();
                            }
                        });
                    }
                    //7). 断开连接
                    connection.disconnect();
                } catch (MalformedURLException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
        }).start();

    }

}

下载图片



public class MainActivity extends AppCompatActivity {

    private ImageView iv;

    private String imageurl = "http://img06.tooopen.com/images/20161106/tooopen_sl_185050524199.jpg";
    private Bitmap bitmap;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        iv = (ImageView) findViewById(R.id.iv_show);

        findViewById(R.id.load).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                new Thread(loadrunable).start();
            }
        });
    }


    private Runnable loadrunable = new Runnable() {

        private InputStream is;

        @Override
        public void run() {

            try {
                URL imgUrl = new URL(imageurl);
                // 使用HttpURLConnection打开连接
                HttpURLConnection urlConn = (HttpURLConnection) imgUrl
                        .openConnection();
                urlConn.setDoInput(true);
                urlConn.setDoOutput(false);
                urlConn.setRequestMethod("GET");
                urlConn.setConnectTimeout(3000);
                urlConn.setUseCaches(true);
                urlConn.connect();
                int code = urlConn.getResponseCode();
                Log.e("tag", "run: "+code );
                // 将得到的数据转化成InputStream
                InputStream is = urlConn.getInputStream();
                // 将InputStream转换成Bitmap
//            bitmap = getBitmapInputStream(is);

                byte[] bytesInputStream = getBytesInputStream(is);
                bitmap = BitmapFactory.decodeByteArray(bytesInputStream,0,bytesInputStream.length);

                Message msgone = new Message();
                msgone.what = 1;
                handler.sendMessage(msgone);


            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }finally {

                if (null != is){
                    try {
                        is.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    };

    private Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
//            super.handleMessage(msg);
            Log.e("tag", "handleMessage: "+msg.what );

            if (null != bitmap && null != iv){
                iv.setImageBitmap(bitmap);
            }
        }
    };

    public Bitmap getBitmapInputStream(InputStream is){
        Bitmap bp;
        bp = BitmapFactory.decodeStream(is);

        return bp;
    }

    public byte[] getBytesInputStream( InputStream is) throws IOException {

        ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream();
        byte[] buff = new byte[512];
        int len;
        while ((len = is.read(buff))!= -1){

            arrayOutputStream.write(buff,0,len);
        }

        is.close();
        arrayOutputStream.close();

        return arrayOutputStream.toByteArray();

    }
}


重点:不要设置setDoOutput(true),post请求上传参数得设置为true;
它默认为false:  urlConn.setDoOutput(false);

 

三、使用HttpClient

1.HttpClient/DefaultHttpClient : 能提交请求的客户端对象 

HttpResponse execute (HttpUriRequest request) 

执行包含请求数据的请求对象, 返回包含响应数据的响应对象 

HttpParams getParams()

得到包含请求参数的对象 

1.: HttpConnectionParams : 设置请求参数的工具类 

static setConnectionTimeout(params, time) : 设置获取连接的超时时间 

static setSoTimeout(params, time): 设置读取数据的超时时间 

2.HttpGet : Get请求 

HttpGet(String path) : 包含请求路径的构造方法 

3.HttpPost : Post请求 

HttpPost(String path) : 包含请求路径的构造方法 

setEntity(HttpEntity entity) : 设置请求体 

 

6、使用HttpClient(2)

1.NameValuePair/BasicNameValuePair : 包含参数键值对 

BasicNameValuePair (String name, String value) 

2.HttpResponse : 服务器返回的响应 

getStatusLine() : 得到响应状态行, 从而得到状态码 

getEntity() : 得到响应体数据对象 

3.EntityUtils : 解析HttpEntity的工具类 

toString(httpEntity):  解析响应体, 得其内容字符串 

4.  关闭连接, 释放资源:

client.getConnectionManager().shutdown();

权限:

 <!-- 联网 --><uses-permission android:name="android.permission.INTERNET"/>

public class MainActivity extends Activity {

    private EditText et_main_message;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        et_main_message=findViewById(R.id.et_main_message);
    }


    public void get(View v) throws IOException {
        //1. 显示ProgressDialog
        final ProgressDialog dialog= ProgressDialog.show(this,null,"正在加载中");
        //2. 启动分线程
        new Thread(new Runnable() {
            //3. 在分线程, 发送请求, 得到响应数据
            @Override
            public void run() {
                try {
                    //1). 得到path, 并带上参数
                    String path="http://192.168.0.118/test.php?id=2";
                    //2). 创建HttpClient对象
                    HttpClient httpClient=new DefaultHttpClient();
                    //3). 设置超时
                    HttpParams params=httpClient.getParams();
                    HttpConnectionParams.setConnectionTimeout(params,2000);
                    HttpConnectionParams.setSoTimeout(params,3000);
                    //4). 创建请求对象
                    HttpGet request=new HttpGet(path);
                    //5). 执行请求对象, 得到响应对象
                    HttpResponse response= httpClient.execute(request);
                    int code=response.getStatusLine().getStatusCode();
                    if(code==200){
                        //6). 得到响应体文本
                        HttpEntity entity=response.getEntity();
                        final String result=EntityUtils.toString(entity);
                        //4. 要主线程, 显示数据, 移除dialog
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                et_main_message.setText(result);
                                dialog.dismiss();
                            }
                        });
                    }
                    //7). 断开连接
                    httpClient.getConnectionManager().shutdown();

                } catch (IOException e) {
                    e.printStackTrace();
                    //如果出了异常要移除dialog
                    dialog.dismiss();
                }
            }
        }).start();

    }


    public void post(View v){
        //1. 显示ProgressDialog
        final ProgressDialog dialog= ProgressDialog.show(this,null,"正在加载中");
        //2. 启动分线程
        new Thread(new Runnable() {
            @Override
            public void run() {

                try {
                    //1). 得到path, 并带上参数
                    String path="http://192.168.0.118/test.php";
                    //2). 创建HttpClient对象
                    HttpClient httpClient=new DefaultHttpClient();
                    //3). 设置超时
                    HttpParams params=httpClient.getParams();
                    HttpConnectionParams.setConnectionTimeout(params,2000);
                    HttpConnectionParams.setSoTimeout(params,3000);
                    //4). 创建请求对象
                    HttpPost request=new HttpPost(path);
                    //设置请求体
                    List<BasicNameValuePair> parameters=new ArrayList<BasicNameValuePair>();
                    parameters.add(new BasicNameValuePair("id","123"));
                    parameters.add(new BasicNameValuePair("name","haitao"));
                    HttpEntity entity=new UrlEncodedFormEntity(parameters);
                    request.setEntity(entity);
                    //5). 执行请求对象, 得到响应对象
                    HttpResponse response=httpClient.execute(request);
                    int code=response.getStatusLine().getStatusCode();
                    if(code ==200){
                        //6). 得到响应体文本
                        entity=response.getEntity();
                        final String result=EntityUtils.toString(entity);
                        //4. 要主线程, 显示数据, 移除dialog
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                et_main_message.setText(result);
                                dialog.dismiss();
                            }
                        });

                    }
                    //7). 断开连接
                    httpClient.getConnectionManager().shutdown();

                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                    dialog.dismiss();
                } catch (ClientProtocolException e) {
                    e.printStackTrace();
                    dialog.dismiss();
                } catch (IOException e) {
                    e.printStackTrace();
                    dialog.dismiss();
                }

            }
        }).start();
    }

}

 

四、Android Studio中添加对HttpClient的支持包

sdk6.0以后取消了HttpClient,设置android SDK的编译版本为23时,且使用了httpClient相关类的库项目,会出现有一些类找不到的错误。

解决方法有两种:

1.在相应的module下的build.gradle中加入:

useLibrary 'org.apache.http.legacy'

这条语句一定要加在 android{ } 当中。

如:

android {

    useLibrary 'org.apache.http.legacy'

}

2.将在相应的module下的build.gradle中修改compileSdkVersion的值,设置为更小的sdk版本

 

 

一、Volley

Volley是Google 2013年的 I/O大会 上,发布了的一个框架 

Volley是Android上的网络通信库,能使网络通信更快,更简单,更健壮 

Volley特别适合数据量不大但是通信频繁的场景: 带图片的列表

http://www.cnblogs.com/cpacm/p/4193011.html

Volley框架的使用

http://blog.csdn.net/guolin_blog/article/details/17482095

所谓Volley,它是2013年Google I/O上发布的一款网络框架,基于Android平台,能使网络通信更快,更简单,更健全。

它的优点:

 (1)默认Android2.3及以上基于HttpURLConnection,2.3以下使用基于HttpClient;

 (2)符合Http 缓存语义 的缓存机制(提供了默认的磁盘和内存等缓存);

 (3)请求队列的优先级排序;

 (4)提供多样的取消机制;

 (5)提供简便的图片加载工具(其实图片的加载才是我们最为看重的功能);

 (6)一个优秀的框架。

不足之处也有:

  (1)它只适合数据量小,通信频繁的网络操作,

  (2)如果是数据量大的,像音频,视频等的传输,还是不要使用Volley的为好。

2、Volley相关API

1.RequestQueue :  请求队列, 会自动执行队列中的请求 

Volley. newRequestQueue(context) : 创建一个请求队列 

addReqeust(Request reqeust) : 将请求添加到请求队列 

2.Request<T>: 代表请求的接口 

StringRequest : 获取字符串结果的请求 

JsonRequest : 获取Json数据结果的请求 

ImageRequest : 获取图片结果的请求 

权限:<!-- 联网 --> <uses-permission android:name="android.permission.INTERNET"/>

public class MainActivity extends Activity {

    private EditText et_main_message;
    private RequestQueue queue;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        et_main_message=findViewById(R.id.et_main_message);
        queue= Volley.newRequestQueue(this);
    }

    /*
    * 使用Volley提交get请求
    */
   /*
    1. 创建请求队列对象(一次)
    2. 创建请求对象StringRequest
    3. 将请求添加到队列中
    */
    public void get(View v){
        final ProgressDialog dialog = ProgressDialog.show(this, null, "正在请求中...");
        //创建请求对象StringRequest
        String path ="http://192.168.0.118/test.php?id=2";
        //创建请求对象StringRequest
        StringRequest request=new StringRequest(path, new Response.Listener<String>() {
            @Override
            public void onResponse(String response) {//在主线程执行
                et_main_message.setText(response);
                dialog.dismiss();
            }
        }, null);
        queue.add(request);
    }

    /*
    * 使用Volley提交post请求
    */
    public void post(View v){
        final ProgressDialog dialog = ProgressDialog.show(this, null, "正在请求中...");
        String path="http://192.168.0.118/test.php";
        //创建请求对象StringRequest
        StringRequest request=new StringRequest(Request.Method.POST, path, new Response.Listener<String>() {
            @Override
            public void onResponse(String response) {
                et_main_message.setText(response);
                dialog.dismiss();
            }
        },null){
            //重写此方法返回参数的map作为请求体
            @Override
            protected Map<String, String> getParams() throws AuthFailureError {
                Map<String,String> map=new HashMap<String,String>();
                map.put("id","1");
                map.put("name","haitao");
                return map;
            }
        };
        queue.add(request);
    }

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值