Android中版本更新(使用HttpURLConnection网络请求)
2017-09-08 12:33
435 查看
版本更新是每款应用不可缺少的环节之一 , 为了方便之后的集成 , 现在记录一下 , 目前使用的是HttpURLConnection进行网络请求 , 后期会使用其它网络请求优化.
启动页后调用方法:
获取升级信息的方法:
弹出提示框方法,已经存在,是重新下载还是直接安装:
安装apk的方法:
下载apk的方法:
弹出下载apk的对话框方法:
获取当前时间的方法:
自定义版本更新对话框:
自定义本机上已存在apk的对话框:
自定义对话框布局:
版本更新的bean类:
启动页后调用方法:
private UpdateInfo iwudif;//版本更新bean类 private String path = "";//请求路径 // 检测版本是否一致, private void isNeedUpdate() { new Thread(new Runnable() { @Override public void run() { iwudif = getUpDateInfo(path);//调用网络请求的方法,获取后台配置的请求数据,path为请求路径 if (null == iwudif) { Log.d("text", "没有更新"); runOnUiThread(new Runnable() { @Override public void run() { jumpToI8LoginActivity();//进入到登录界面 } }); } else { Log.d("text", "有更新"); apkName = I8SP.getDownloadBag(TCSplashActivity.this);//保存apk的name到sp中 runOnUiThread(new Runnable() { @Override public void run() { if (iwudif.getMsg().getUrl() != null) {//有更新 if (UPDATATYPE == iwudif.getMsg().getUpdateType()) { File file = new File(Environment.getExternalStorageDirectory() .getAbsolutePath(), apkName); //新版本存在,直接安装 if (file.exists()) { try { String md5ByFile = StatusBarUtil.getMd5ByFile(file); //判定md5值是否正确存在进入已存在更新,不存在进入show的对话框 if (null != md5ByFile && md5ByFile.equals(iwudif .getMsg().getMd5())) { //弹出提示框,已经存在,是重新下载还是直接安装。 existApkInstall(iwudif); } else { //apk没下载,是否更新对话框 showUpdateDialog(iwudif); } } catch (FileNotFoundException e) { e.printStackTrace(); jumpToI8LoginActivity();//进入到登录界面 } } else { //apk没下载,是否更新对话框 showUpdateDialog(iwudif); } } else { //强制更新时进入是否更新对话框 showUpdateDialog(iwudif); } } else {//无更新 //版本号一致,进入主界面 jumpToI8LoginActivity();//进入到登录界面 } } }); } } }).start(); }
获取升级信息的方法:
/** * 获取升级信息 */ public UpdateInfo getUpDateInfo(String path) { StringBuffer sb = new StringBuffer(); String line; BufferedReader reader = null; try { // 创建一个url对象 URL url = new URL(path); // 通過url对象,创建一个HttpURLConnection对象(连接) HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(); urlConnection.setRequestMethod("GET"); urlConnection.setConnectTimeout(2000); urlConnection.setReadTimeout(2000); if (urlConnection.getResponseCode() == 200) { // 通过HttpURLConnection对象,得到InputStream reader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream(), "UTF-8")); while ((line = reader.readLine()) != null) { sb.append(line); } String info = sb.toString(); Log.d("text", "版本升级信息:" + info);//-------- // 对升级的信息进行封装 Gson gson = new Gson(); Type type = new TypeToken<UpdateInfo>() { }.getType(); return gson.fromJson(info, type); } } catch (Exception e) { e.printStackTrace(); return null; } finally { try { if (reader != null) { reader.close(); } } catch (Exception e) { e.printStackTrace(); } } return null; }
弹出提示框方法,已经存在,是重新下载还是直接安装:
//是否重新下载 private void existApkInstall(final UpdateInfo iwudif) { ExistVersionUpdataDialog existVersionUpdataDialog = new ExistVersionUpdataDialog(iwudif.getMsg().getDesc(), iwudif.getMsg() .getUpdateType(), this, "版本更新", "温馨提示:检测到本机已存在最新版本的安装包" + apkName + ",可选择立即安装或重新下载。", "立即安装", "重新下载", new ExistVersionUpdataDialog .ExistVersionUpdataDialogCallBack() { @Override public void sureUpdata(boolean isUpdata) { installApk(); } @Override public void downloadAgain(boolean isUpdata) { downFile(iwudif.getMsg().getUrl()); } @Override public void close(boolean isUpdata) { jumpToI8LoginActivity();//进入到登录界面 } }); //按对话框外区域不消失 existVersionUpdataDialog .setCanceledOnTouchOutside(false); //按返回键也不起作用 existVersionUpdataDialog .setCancelable(false); existVersionUpdataDialog .show(); }
安装apk的方法:
//安装apk,也可以进行静默安装 private void installApk() { //更新后自动打开apk Intent intent = new Intent(Intent.ACTION_VIEW); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);//如果不加,最后安装完成,点打开,无法打开新版本应用。 intent.setDataAndType(Uri.fromFile(new File(Environment.getExternalStorageDirectory(), apkName)), "application/vnd.android.package-archive"); startActivityForResult(intent, 10); android.os.Process.killProcess(android.os.Process.myPid());//如果不加,最后不会提示完成、打开。 }
下载apk的方法:
/** * 下载最新版本的apk * * @param path apk下载地址 private void downFile(final String path) { final ProgressDialog pBar = new ProgressDialog(TCSplashActivity.this); pBar.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); pBar.setCancelable(false); pBar.setTitle("正在下载..."); pBar.setMessage("请稍候..."); pBar.setProgress(0); pBar.show(); new Thread() { public void run() { try { URL url = new URL(path); HttpURLConnection con = (HttpURLConnection) url.openConnection(); con.setReadTimeout(3000); con.setConnectTimeout(3000); con.setRequestProperty("Charset", "UTF-8"); con.setRequestMethod("GET"); if (con.getResponseCode() == 200) { int length = con.getContentLength();// 获取文件大小 InputStream is = con.getInputStream(); pBar.setMax(100); // 设置进度条的总长度 FileOutputStream fileOutputStream = null; if (is != null) { // 对apk进行保存 String[] split = getPackageName().split("\\."); int length1 = split.length - 1; 4000 apkName = "apkshow_" + split[length1] + "_" + getTime() + ".apk"; I8SP.setDownloadBag(TCSplashActivity.this, apkName); File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath(), apkName); fileOutputStream = new FileOutputStream(file); byte[] buf = new byte[1024]; int ch; int process = 0; while ((ch = is.read(buf)) != -1) { fileOutputStream.write(buf, 0, ch); process += ch; pBar.setProgress(process * 100 / length); // 实时更新进度了 } } if (fileOutputStream != null) { fileOutputStream.flush(); fileOutputStream.close(); } //ui线程,然后进入主线程 runOnUiThread(new Runnable() { @Override public void run() { // 将下载进度对话框取消 pBar.cancel(); installApk(); } }); } } catch (Exception e) { e.printStackTrace(); runOnUiThread(new Runnable() { @Override public void run() { pBar.cancel(); Toast.makeText(getApplicationContext(), "下载失败", Toast.LENGTH_LONG).show(); jumpToI8LoginActivity();//进入到登录界面 } }); } } }.start(); }
弹出下载apk的对话框方法:
/** * 显示升级信息的对话框 */ private void showUpdateDialog(final UpdateInfo iwudif) { VersionUpdataDialog dialog = new VersionUpdataDialog (iwudif.getMsg().getDesc(), iwudif.getMsg().getUpdateType(), this, "版本升级", "请升级APP版本至" + iwudif.getMsg().getVersion() + ":", "更新", "取消", new VersionUpdataDialog .VersionUpdataDialogCallBack() { @Override public void sureDelete(boolean isUpdata) { downFile(iwudif.getMsg().getUrl());// 点击确定将apk下载 } @Override public void close(boolean isUpdata) { //MobclickAgent.onKillProcess(TCSplashActivity.this); android.os.Process.killProcess(android.os.Process.myPid()); jumpToI8LoginActivity();//进入到登录界面 } @Override public void cancle(boolean isUpdata) { //isHaveHotUpdata();//判断是否有热更新 jumpToI8LoginActivity();//进入到登录界面 } }); //按对话框外区域不消失 dialog.setCanceledOnTouchOutside(false); //按返回键也不起作用 dialog.setCancelable(false); dialog.show(); }
获取当前时间的方法:
//获取当前时间 public static String getTime() { SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd"); Date curDate = new Date(System.currentTimeMillis());//获取当前时间 return formatter.format(curDate); }
自定义版本更新对话框:
import android.app.Dialog; import android.content.Context; import android.os.Bundle; import android.util.Log; import android.view.KeyEvent; import android.view.View; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import com.i8dayou.an.zb.i8login.utils.CommonUtils; public class I8ShowVersionUpdataDialog extends Dialog { public interface I8WanVersionUpdataDialogCallBack { void sureDelete(boolean isUpdata); void close(boolean isUpdata); void cancle(boolean isUpdata); } private String mUpdateContent; private int updateType; private Context mContext; private String mTitle; private String mTipContent; private I8ShowVersionUpdataDialog.I8WanVersionUpdataDialogCallBack mI8WanVersionUpdataDialogCallBack; // 标识是帐号登录还是手机登录;手机0,帐号1 private TextView tv_Title; private TextView tv_tip; private TextView tv_sure; private TextView tv_think; private ImageView tv_close; private String sureText; private String thinkText; private int contentViewWidth = -1; private TextView constraintUpdata; private LinearLayout OptionUpdata; private int UPDATATYPE = 0; //为0时是选择更新, public I8ShowVersionUpdataDialog(String UpdataContent, int type, Context mContext, String mTitle, String mTipText, String sureText, String thinkText, I8WanVersionUpdataDialogCallBack mI8WanVersionUpdataDialogCallBack) { super(mContext); mUpdateContent = UpdataContent; updateType = type; this.mContext = mContext; this.mTitle = mTitle; this.mTipContent = mTipText; this.sureText = sureText; this.thinkText = thinkText; // this.contentViewWidth = width; this.mI8WanVersionUpdataDialogCallBack = mI8WanVersionUpdataDialogCallBack; } protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getContext().setTheme(CommonUtils.getIdByName("i8_dialog_login", "style", mContext.getPackageName(), mContext)); View contentView = View.inflate(mContext, CommonUtils.getIdByName("i8wan_version_updata_dialog", "layout", mContext.getPackageName(), mContext), null); setContentView(contentView); if (contentViewWidth > 0) contentView.getLayoutParams().width = contentViewWidth; tv_Title = (TextView) findViewById( CommonUtils.getIdByName("i8_comfirm_dialog_title", "id", mContext.getPackageName(), mContext)); tv_tip = (TextView) findViewById( CommonUtils.getIdByName("i8_comfirm_dialog_tipText", "id", mContext.getPackageName(), mContext)); tv_sure = (TextView) findViewById( CommonUtils.getIdByName("i8_comfirm_dialog_sureDelete", "id", mContext.getPackageName(), mContext)); tv_think = (TextView) findViewById( CommonUtils.getIdByName("i8_comfirm_dialog_think", "id", mContext.getPackageName(), mContext)); constraintUpdata = (TextView) findViewById( CommonUtils.getIdByName("tv_constraintUpdata", "id", mContext.getPackageName(), mContext)); OptionUpdata = (LinearLayout) findViewById( CommonUtils.getIdByName("ll_OptionUpdata", "id", mContext.getPackageName(), mContext)); tv_close = (ImageView) findViewById( CommonUtils.getIdByName("i8_comfirm_dialog_close", "id", mContext.getPackageName(), mContext)); // tv_Title.setText(mTitle); // tv_tip.setText(mTipContent + "\n" + "\n" + mUpdateContent); tv_tip.setText(mUpdateContent);//普通更新不要显示第一行的mTipContent内容了。 //选择更新 Log.d("text","AAAAAAupdateType=="+updateType);//--------------- if (UPDATATYPE == updateType) { tv_sure.setText(sureText); tv_think.setText(thinkText); tv_sure.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { mI8WanVersionUpdataDialogCallBack.sureDelete(true); I8ShowVersionUpdataDialog.this.dismiss(); } }); tv_think.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { mI8WanVersionUpdataDialogCallBack.cancle(true); I8ShowVersionUpdataDialog.this.dismiss(); } }); Log.d("text","AAAAAA选择更新");//--------------- //强制更新 } else { Log.d("text","AAAAAA强制更新");//--------------- tv_close.setVisibility(View.VISIBLE); tv_close.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { mI8WanVersionUpdataDialogCallBack.close(true); I8ShowVersionUpdataDialog.this.dismiss(); } }); OptionUpdata.setVisibility(View.GONE); constraintUpdata.setVisibility(View.VISIBLE); constraintUpdata.setText(sureText); constraintUpdata.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { mI8WanVersionUpdataDialogCallBack.sureDelete(true); I8ShowVersionUpdataDialog.this.dismiss(); mI8WanVersionUpdataDialogCallBack.cancle(true); } }); } } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { return true; } }
自定义本机上已存在apk的对话框:
import android.app.Dialog; import android.content.Context; import android.os.Bundle; import android.view.KeyEvent; import android.view.View; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import com.i8dayou.an.zb.i8login.utils.CommonUtils; public class I8ShowExistVersionUpdataDialog extends Dialog{ public interface i8ShowExistVersionUpdataDialogCallBack { void sureUpdata(boolean isUpdata); void downloadAgain(boolean isUpdata); void close(boolean isUpdata); } private String mUpdateContent; private int updateType; private Context mContext; private String mTitle; private String mTipContent; private I8ShowExistVersionUpdataDialog.i8ShowExistVersionUpdataDialogCallBack mi8ShowExistVersionUpdataDialogCallBack; private TextView tv_Title; private ImageView close; private TextView tv_tip; private TextView tv_sure; private TextView tv_think; private String sureText; private String thinkText; private TextView constraintUpdata; private LinearLayout OptionUpdata; public I8ShowExistVersionUpdataDialog(String UpdataContent, int type, Context mContext, String mTitle, String mTipText, String sureText, String thinkText, I8ShowExistVersionUpdataDialog.i8ShowExistVersionUpdataDialogCallBack i8ShowExistVersionUpdataDialogCallBack) { super(mContext); mUpdateContent = UpdataContent; updateType = type; this.mContext = mContext; this.mTitle = mTitle; this.mTipContent = mTipText; this.sureText = sureText; this.thinkText = thinkText; this.mi8ShowExistVersionUpdataDialogCallBack = i8ShowExistVersionUpdataDialogCallBack; } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getContext().setTheme(CommonUtils.getIdByName("i8_dialog_login", "style", mContext.getPackageName(), mContext)); View contentView = View.inflate(mContext, CommonUtils.getIdByName("i8wan_version_updata_dialog", "layout", mContext.getPackageName(), mContext), null); setContentView(contentView); tv_Title = (TextView) findViewById( CommonUtils.getIdByName("i8_comfirm_dialog_title", "id", mContext.getPackageName(), mContext)); close = (ImageView) findViewById( CommonUtils.getIdByName("i8_comfirm_dialog_close", "id", mContext.getPackageName(), mContext)); tv_tip = (TextView) findViewById( CommonUtils.getIdByName("i8_comfirm_dialog_tipText", "id", mContext.getPackageName(), mContext)); tv_sure = (TextView) findViewById( CommonUtils.getIdByName("i8_comfirm_dialog_sureDelete", "id", mContext.getPackageName(), mContext)); tv_think = (TextView) findViewById( CommonUtils.getIdByName("i8_comfirm_dialog_think", "id", mContext.getPackageName(), mContext)); constraintUpdata = (TextView) findViewById( CommonUtils.getIdByName("tv_constraintUpdata", "id", mContext.getPackageName(), mContext)); OptionUpdata = (LinearLayout) findViewById( CommonUtils.getIdByName("ll_OptionUpdata", "id", mContext.getPackageName(), mContext)); close.setVisibility(View.VISIBLE); tv_Title.setText(mTitle); tv_tip.setText(mTipContent + "\n" + "\n" + mUpdateContent); tv_sure.setText(sureText); tv_think.setText(thinkText); tv_sure.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { mi8ShowExistVersionUpdataDialogCallBack.sureUpdata(true); I8ShowExistVersionUpdataDialog.this.dismiss(); } }); tv_think.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { mi8ShowExistVersionUpdataDialogCallBack.downloadAgain(true); I8ShowExistVersionUpdataDialog.this.dismiss(); } }); close.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { mi8ShowExistVersionUpdataDialogCallBack.close(true); I8ShowExistVersionUpdataDialog.this.dismiss(); } }); /*setOnDismissListener(new OnDismissListener() { @Override public void onDismiss(DialogInterface dialogInterface) { Log.d("text","对话框取消-------");//-------------------------- } });*/ } /*@Override public void setOnDismissListener(OnDismissListener listener) { Log.d("text","-----------------对话框取消-------");//-------------------------- super.setOnDismissListener(listener); Log.d("text","===============对话框取消-------");//-------------------------- }*/ @Override public boolean onKeyDown(int keyCode, KeyEvent event) { return true; } }
自定义对话框布局:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/i8_popwin_bg" android:padding="@dimen/I8d6"> <TextView android:id="@+id/i8_comfirm_dialog_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_marginTop="@dimen/I8d5" android:text="Tiele" android:textColor="#353535" android:textSize="17sp"/> <ImageView android:id="@+id/i8_comfirm_dialog_close" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:src="@drawable/i8_popwin_close" android:visibility="gone"/> <ScrollView android:id="@+id/i8_comfirm_dialog_scroll" android:layout_width="match_parent" android:layout_height="191dp" android:layout_below="@+id/i8_comfirm_dialog_title" android:layout_marginBottom="@dimen/I8d8" android:layout_marginLeft="@dimen/I8d12" android:layout_marginRight="@dimen/I8d12" android:layout_marginTop="@dimen/I8d15" android:background="@drawable/i8wan_updata_scroll" android:fillViewport="true" android:scrollbarSize="4sp" android:scrollbarThumbVertical="@color/scrollball" android:scrollbars="vertical"> <!-- android:scrollbarStyle="outsideOverlay" android:scrollbarSize="3sp" android:fadeScrollbars="false" android:scrollbarThumbVertical="@color/scrollball" android:background="@drawable/i8_find_password_success_message_bg"--> <TextView android:id="@+id/i8_comfirm_dialog_tipText" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center_vertical" android:paddingLeft="14dp" android:paddingRight="12dp" ba71 android:textColor="#353535" android:lineSpacingExtra="8dp" android:textSize="15sp"/> </ScrollView> <!-- <TextView android:id="@+id/i8_comfirm_dialog_tipText" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@+id/i8_comfirm_dialog_title" android:layout_marginBottom="@dimen/I8d8" android:layout_marginLeft="@dimen/I8d12" android:layout_marginRight="@dimen/I8d12" android:layout_marginTop="@dimen/I8d15" android:background="@drawable/i8_find_password_success_message_bg" android:gravity="center_vertical" android:textColor="#353535" android:textSize="15sp"/>--> <RelativeLayout android:id="@+id/rl_constraintUpdata" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@+id/i8_comfirm_dialog_scroll" android:padding="@dimen/I8d6"> <TextView android:id="@+id/tv_constraintUpdata" android:layout_width="match_parent" android:layout_height="48dp" android:layout_marginRight="@dimen/I8d6" android:background="@drawable/i8_login_bg_blue" android:gravity="center" android:text="更新" android:textColor="@android:color/white" android:textSize="17sp" android:visibility="gone"/> <LinearLayout android:id="@+id/ll_OptionUpdata" android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:id="@+id/i8_comfirm_dialog_sureDelete" android:layout_width="@dimen/I8d0" android:layout_height="48dp" android:layout_marginRight="@dimen/I8d6" android:layout_weight="1" android:background="@drawable/i8_login_bg_blue" android:gravity="center" android:text="@string/i8_comfirm_delete" android:textColor="@android:color/white" android:textSize="17sp"/> <TextView android:id="@+id/i8_comfirm_dialog_think" android:layout_width="@dimen/I8d0" android:layout_height="48dp" android:layout_marginLeft="@dimen/I8d6" android:layout_weight="1" android:background="@drawable/i8_popwin_comfirm_think_bg" android:gravity="center" android:text="@string/i8_comfirm_think" android:textColor="@android:color/white" android:textSize="17sp"/> </LinearLayout> </RelativeLayout>
版本更新的bean类:
public class UpdateInfo { private int status; private UpdateInfoMessage msg; public int getStatus() { return status; } public UpdateInfoMessage getMsg() { return msg; } public void setStatus(int status) { this.status = status; } public void setMsg(UpdateInfoMessage msg) { this.msg = msg; } public class UpdateInfoMessage { private int id; private double version; private String desc; private int channel; private String url; private int updateType; private String md5; private int markCount; private int open; private int space; public int getOpen() { return open; } public int getSpace() { return space; } public void setOpen(int open) { this.open = open; } public void setSpace(int space) { this.space = space; } public void setId(int id) { this.id = id; } public void setVersion(double version) { this.version = version; } public void setDesc(String desc) { this.desc = desc; } public void setChannel(int channel) { this.channel = channel; } public void setUrl(String url) { this.url = url; } public void setUpdateType(int updateType) { this.updateType = updateType; } public void setMd5(String md5) { this.md5 = md5; } public void setMarkCount(int markCount) { this.markCount = markCount; } public int getId() { return id; } public double getVersion() { return version; } public String getDesc() { return desc; } public int getChannel() { return channel; } public String getUrl() { return url; } public int getUpdateType() { return updateType; } public String getMd5() { return md5; } public int getMarkCount() { return markCount; } @Override public String toString() { return "I8WanUpdateInfoMessage{" + "id=" + id + ", version=" + version + ", desc='" + desc + '\'' + ", channel=" + channel + ", url='" + url + '\'' + ", updateType=" + updateType + ", md5='" + md5 + '\'' + ", markCount=" + markCount + '}'; } } }
相关文章推荐
- 【黑马Android】(05)短信/查询和添加/内容观察者使用/子线程网络图片查看器和Handler消息处理器/html查看器/使用HttpURLConnection采用Post方式请求数据/开源项目
- 第十二篇:Android GET请求获取网络数据以及POST数据(使用HttpURLConnection)
- Android使用HttpURLConnection请求网络返回JSON数据并解析
- android中使用 HttpURLConnection 做网络请求
- Android使用HttpURLConnection请求网络资源
- Android中使用HttpURLConnection和HttpClient实现GET和POST请求访问网络
- Android使用HttpURLConnection发送网络请求(笔记)
- Android访问网络,使用HttpURLConnection还是HttpClient?
- Android HttpURLConnection 网络通信实时更新
- Android用httpURLConnection发送post网络请求并拿到数据
- Android访问网络,使用HttpURLConnection还是HttpClient?
- Android访问网络,使用HttpURLConnection还是HttpClient?
- android发送http请求—-URLConnection、HttpURLConnection的使用
- Android访问网络,使用HttpURLConnection还是HttpClient?
- 使用HttpURLConnection和使用HttpClient方式请求网络采用get方式和post方式请求数据
- Android访问网络,使用HttpURLConnection还是HttpClient?
- Android访问网络,使用HttpURLConnection还是HttpClient?
- Android访问网络,使用HttpURLConnection还是HttpClient?
- Android访问网络,使用HttpURLConnection还是HttpClient?
- Android访问网络,使用HttpURLConnection还是HttpClient?