HttpClient网络访问





一、HttpClient网络访问:



(一)、简介:


1、Apache组织提供了HttpClient项目,可以实现网络访问。在Android中,成功集成了HttpClient,所以在Android中可以直接使用HttpClient访问网络。



2、与HttpURLConnection相比,HttpClient将前者中的输入、输出流操作,统一封装成HttpGet、HttpPost、HttpRequest类。



  • HttpClient:网络连接对象;
  • HttpGet:代表发送GET请求;
  • HttpPost:代表发送POST请求;
  • HttpResponse:代表处理服务器响应的对象。
  • HttpEntity对象:该对象中包含了服务器所有的返回内容。

3、使用步骤:(六部曲)【重点】



  1. 创建HttpClient对象:通过实例化DefaultHttpClient获得;
  2. 创建HttpGet或HttpPost对象:通过实例化 HttpGet或HttpPost 获得,而构造方法的参数是urlstring(即需要访问的网络url地址)。也可以通过调用setParams()方法来添加请求参数;
  3. 调用HttpClient对象的execute()方法,参数是刚才创建的 HttpGet或HttpPost对象 ,返回值是HttpResponse对象;
  4. 通过response对象中的getStatusLine()方法和getStatusCode()方法获取服务器响应状态是否是200。
  5. 调用 HttpResponse对象的getEntity()方法,返回HttpEntity对象。而该对象中包含了服务器所有的返回内容。
  6. 借助EntityUtils的toString()方法或toByteArray()对 HttpEntity对象进行处理,也可以通过IO流对 HttpEntity对象进行操作。






(二)、封装HttpClientHelper工具类:




public class
public static
HttpClient httpClient = new
HttpGet request = new
HttpResponse httpResponse = null;
try
httpResponse = httpClient.execute(request);
if
return
}
} catch
e.printStackTrace();
} catch
e.printStackTrace();
}
return null;
}

/**
 * 作用:实现网络访问文件,将获取到数据储存在文件流中
 * 
@param
url地址
@return inputstream
 */
public static
HttpClient httpClient = new
HttpGet requestGet = new
HttpResponse httpResponse;
try
httpResponse = httpClient.execute(requestGet);
if
HttpEntity entity = httpResponse.getEntity();
return
}
} catch
e.printStackTrace();
}
return null;
}

/**
 * 作用:实现网络访问文件,将获取到的数据存在字节数组中
 * 
@param
url地址
@return
 */
public static byte[] loadByteFromURL(String url) {
HttpClient httpClient = new
HttpGet requestGet = new
try
HttpResponse httpResponse = httpClient.execute(requestGet);
if
HttpEntity httpEntity = httpResponse.getEntity();
return EntityUtils.toByteArray(httpEntity);
}
} catch
e.printStackTrace();
System.out.println("====>"
}
return null;
}

/**
 * 作用:实现网络访问文件,返回字符串
 * 
@param
url地址
@return
 */
public static
HttpClient httpClient = new
HttpGet requestGet = new
try
HttpResponse httpResponse = httpClient.execute(requestGet);
if
HttpEntity httpEntity = httpResponse.getEntity();
return EntityUtils.toString(httpEntity, "utf-8");
}
} catch
e.printStackTrace();
}
return null;
}

/**
 * 作用:实现网络访问文件,先给服务器通过“GET”方式提交数据,再返回相应的数据
 * 
@param
url地址
@param
url:访问url时,需要传递给服务器的参数。
username=wangxiangjun&password=123456
@return
 */
public static byte[] doGetSubmit(String url, String params) {
HttpClient httpClient = new
HttpGet requestGet = new HttpGet(url + "?"
try
HttpResponse httpResponse = httpClient.execute(requestGet);
if
HttpEntity httpEntity = httpResponse.getEntity();
return EntityUtils.toByteArray(httpEntity);
}
} catch
e.printStackTrace();
}
return null;
}

/**
 * 作用:实现网络访问文件,先给服务器通过“POST”方式提交数据,再返回相应的数据
 * 
@param
url地址
@param
url:访问url时,需要传递给服务器的参数。 第二个参数为:List<NameValuePair>
@return
 */
public static byte[] doPostSubmit(String url, List<NameValuePair> params) {
HttpClient httpClient = new
HttpPost requestPost = new
try
requestPost.setEntity(new UrlEncodedFormEntity(params, "utf-8"));
HttpResponse httpResponse = httpClient.execute(requestPost);
if
HttpEntity httpEntity = httpResponse.getEntity();
return EntityUtils.toByteArray(httpEntity);
}
} catch
e.printStackTrace();
}
return null;
}

/**
 * 作用:实现网络访问文件,先给服务器通过“POST”方式提交数据,再返回相应的数据
 * 
@param
url地址
@param
url:访问url时,需要传递给服务器的参数。 Map<String , Object>
@return
 */
public static byte[] doPostSubmit(String url, Map<String, Object> params) {
HttpClient httpClient = new
HttpPost requestPost = new

List<BasicNameValuePair> parameters = new
try
if (params != null) {
for
String key = entry.getKey();
String value = entry.getValue().toString();
BasicNameValuePair nameValuePair = new
key, value);
parameters.add(nameValuePair);
}
}
requestPost
.setEntity(new UrlEncodedFormEntity(parameters, "utf-8"));
HttpResponse httpResponse = httpClient.execute(requestPost);

if
HttpEntity httpEntity = httpResponse.getEntity();
return EntityUtils.toByteArray(httpEntity);
}
} catch
e.printStackTrace();
}
return null;
}
}







【复习:】POST和GET在表单提交时的区别:【重点】



  Post传递必须依赖于表单,传值的内容没有大小限制,传值内容不会在地址栏显示,比 Get 传值安全;



  Get传值的内容会通过地址栏显示,而地址栏长度有最大长度限制,因为 Get 传参内容不可以过长,当超过某个长度后会自动裁切掉多余内容。比起 Post 传参, Get 传参不够安全。但是 Get 传参可以通过表单,也可以不通过表单,直接通过地址栏传参。因此 Get 传参更灵活。






二、SoundPool声音池:



(一)、使用步骤:



1、创建SoundPool对象;



SoundPool pool = new SoundPool(5, AudioManager.STREAM_MUSIC, 0);


2、加载音效;



     

pool.load(this, R.raw.音频文件名, 1);

3、播放音效。



pool.play(int soundID, float leftVolume, float rightVolume, int priority, int loop, float rate) ;

  





(二)、示例代码:



public class MainActivity extends Activity {

     private SoundPool pool = null;

     private HashMap<Integer, Integer> poolMap = null;




    @Override

     protected void onCreate(Bundle savedInstanceState) {

             super.onCreate(savedInstanceState);

             setContentView(R.layout.activity_main);

             // 调用初始化声音池

             initSoundPool();

     }




     /*

    * 初始化声音池 pool = new SoundPool(5, // maxStreams参数,该参数为设置同时能够播放多少音效

    * AudioManager.STREAM_MUSIC, //

    * streamType参数,该参数设置音频类型,在游戏中通常设置为:STREAM_MUSIC //

    * srcQuality参数,该参数设置音频文件的质量,0为默认值。

    */

     public void initSoundPool() {

             pool = new SoundPool(5, AudioManager.STREAM_MUSIC, 0);

             poolMap = new HashMap<Integer, Integer>();

             poolMap.put(1, pool.load(this, R.raw.ding, 1));

             poolMap.put(2, pool.load(this, R.raw.ringin, 1));

     }




     /*

    * 播放声音,参数sound是播放音效的id,参数number是播放音效的次数 pool.play(poolMap.get(sound), //

    * 播放的音乐id volumnRatio, // 左声道音量 volumnRatio, // 右声道音量 1, // 优先级,0为最低

    * number, // 循环次数,0无不循环,-1无永远循环 1 // 回放速度 ,该值在0.5-2.0之间,1为正常速度

    */

     public void playSound(int sound, int number) {

             // 实例化AudioManager对象

             AudioManager manager = (AudioManager) this

                             .getSystemService(this.AUDIO_SERVICE);

             // 返回当前AudioManager对象的最大音量值

             float audioMaxVolumn = manager

                             .getStreamMaxVolume(AudioManager.STREAM_MUSIC);

             // 返回当前AudioManager对象的音量值

             float audioCurrentVolumn = manager

                             .getStreamVolume(AudioManager.STREAM_MUSIC);

             float volumnRatio = audioCurrentVolumn / audioMaxVolumn;

             pool.play(poolMap.get(sound), // 播放的音乐id

                             volumnRatio, // 左声道音量

                             volumnRatio, // 右声道音量

                                1, // 优先级,0为最低

                                number, // 循环次数,0:不循环,-1:永远循环

                                1 // 回放速度 ,该值在0.5-2.0之间,1为正常速度

             );

     }


 public void clickButton(View view) {

             switch (view.getId()) {

               case R.id.button_main_play1:

                     playSound(1, 0);

                     break;

               case R.id.button_main_play2:

                     playSound(2, 0);

             default:

                     break;
           }
 }
}








三、学习Android的软件Android manual的思考:



(一)、解压android_manual.apk,发现res目录下有个目录raw,其中存放的就是该应用的数据库文件。



1、raw目录是什么?



2、如何访问raw目录下的数据库呢?






(二)、回顾资源访问:



  1. 字符串资源文件:string
  2. 颜色资源、尺寸资源文件 :color、dimen
  3. 布局资源: layout
  4. 数组资源: string-array 、 integer-array
  5. 图片资源: drawable
  6. 样式和主题资源:style、theme
  7. 菜单资源: menu
  8. 原始XML资源: xml
  9. 原生文件资源: raw

【备注:】raw目录下主要放置的资源有音频、视频等文件。raw目录下的文件会在R.java中被注册。


        如何访问raw目录下的文件?



InputStream is = getResources().openRawResource(R.raw.文件名);






【备注:】



        Android manual这个app中将数据库放在raw中,那么该数据库将如何访问?我们发现,当安装完该apk后,会看到在sdcard中产生一个androidmanual目录,该目录下存放着该app的数据库。虽然raw中的数据库是没有办法让SQLiteDatabase访问,而如果放在sdcard上,只要知道路径,则可以访问。所以如果我们要模仿制作一个Android manual



项目,那么就可以借助getResources().openRawResource(R.raw.文件名)产生的输入流,将文件保存在sdcard的某个目录下。这样SQLiteDatabase就可以调用openDatabase()方法来访问数据库了。特别提醒的是:要注意openDatabase()方法的第三个参数flag。如果选择不正确,则无法正常访问数据库。(应该是哪个常量值呢?请同学们先查看API,自己寻找答案。)









四、assets目录中的图片如何访问?



(一)、运用场景:



        当使用WebView控件的时候,可以比较方便地访问assets目录中的文件了。文件目录是: file:///android_asset/文件名.文件后缀






(二)、示例代码:(WebView中载入html字符串,显示assests目录下的图片)



public class MainActivity extends
private WebView webView_main;

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

webView_main = (WebView) findViewById(R.id.webView_main);

// 设置浏览器支持。这样webview可以处理各种通知和请求事件。
// 如果不使用该句代码,在点击超链地址后,会跳出程序,而弹出浏览器访问网页。
webView_main.setWebChromeClient(new
webView_main.setWebViewClient(new

WebSettings webSetting = webView_main.getSettings();
webSetting.setJavaScriptEnabled(true); // 设置支持javascript脚本
webSetting.setAllowFileAccess(true); // 允许访问文件
webSetting.setBuiltInZoomControls(true); // 设置显示缩放按钮
webSetting.setSupportZoom(true); // 支持缩放

String data = "<form method='post' action=''>用户名:<input type='text' name='username'><input type='submit' value='提交'></form>";
StringBuilder sb = new
sb.append("<form method='get' action='http://192.168.104.160:8080/AndroidServer/LoginServlet'>");
sb.append("用户名:<input type='text' name='username'><br>");
sb.append("密码:<input type='password' name='password'><br>");
sb.append("<input type='submit' value='登录'>");
sb.append("</form>");
sb.append("<img src='file:///android_asset/android.jpg' width='300dp'>");

// webview组件能加载包含html代码的字符串,并且能执行html。为了防止乱码,使用loadDataWithBaseURL()方法。而不用loadData()方法。
// loadDataWithBaseURL()方法中的第二个参数时MIME,详见当天的课堂笔记。
webView_main.loadDataWithBaseURL(null, sb.toString(), "text/html",
"utf-8", null);
}




 



(三)、示例代码2:(ImageView中加载assets目录下的图片)



private ImageView imageView_main;

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

imageView_main = (ImageView) findViewById(R.id.imageView_main);
try
InputStream is = this.getAssets().open("abc.jpg");
imageView_main.setImageBitmap(BitmapFactory.decodeStream(is));
} catch
e.printStackTrace();
}
}