Android开发进阶系列(五) 连接服务器下载文件或资源
来源:互联网 发布:oracle查询2列重复数据 编辑:程序博客网 时间:2024/06/05 08:55
对于简单的应用程序,很少会需要连接服务器,单机运行就行了。但是当你需要不断更新软件版本,或者你的APP需要用到大量的资源而直接打包进APK文件太大,这时你就需要连接到服务器去下载文件。下面这个项目就提供了如何连接服务器更新APK和如何下载资源的方法。
连接服务器更新APK
服务器上放置一个记录版本号的txt文件,比如version.txt。放置一个用于更新的APK,比如new.apk
final static String strurl = "http://www.xxx.com/my/version.txt";final static String strurl_apk = "http://www.xxx.com/my/new.apk";
MainActivity的onCreate()方法中调用CheckUpdate()方法
@Overridepublic void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.main); ...... CheckUpdate(); // 检查更新}
连接服务器前当然要先判断网络连接,如果是要下载到SD卡的,还要判断是否有SD卡,判断的代码很简单就不贴上了。
// 检查更新private void CheckUpdate(boolean isAuto) { // 判断版本号,然后下载 downloader = new HttpDownLoader(); int serverVersion = 1; serverVersion = Integer.parseInt(FusionField.downloader.downLoadText(strurl)); if(serverVersion > localVersion) { AlertDialog.Builder builder = new Builder(this); builder.setTitle("软件升级") .setMessage("发现新版本,是否升级!") .setPositiveButton("升级",new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { //开启更新服务UpdateService //这里为了把update更好模块化,可以传一些updateService依赖的值 //如布局ID,资源ID,动态获取的标题,这里以app_name为例 Intent updateIntent =new Intent(MainActivity.this, UpdateService.class); startService(updateIntent); } }) .setNegativeButton("取消", new android.content.DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }); builder.create().show(); }}
UpdateService.class执行后台下载和通知栏下载进度条的更新
public class UpdateService extends Service{//文件存储private File updateDir = null;private File updateFile = null; public static String downloadDir = "/download/";//通知栏private NotificationManager updateNotificationManager = null;private Notification updateNotification = null;//通知栏跳转Intentprivate Intent updateIntent = null;private PendingIntent updatePendingIntent = null;//下载状态private final static int DOWNLOAD_COMPLETE = 0;private final static int DOWNLOAD_FAIL = 1;@Override public void onCreate() { super.onCreate(); } @Overridepublic int onStartCommand(Intent intent, int flags, int startId) { //创建文件 if(android.os.Environment.MEDIA_MOUNTED.equals(android.os.Environment.getExternalStorageState())){ updateDir = new File(Environment.getExternalStorageDirectory(),downloadDir); updateFile = new File(updateDir.getPath(),strurl_apk_name); } this.updateNotificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE); this.updateNotification = new Notification(); //设置下载过程中,点击通知栏,回到主界面 updateIntent = new Intent(this, MainActivity.class); updatePendingIntent = PendingIntent.getActivity(this,0,updateIntent,0); //设置通知栏显示内容 updateNotification.icon = android.R.drawable.stat_sys_download; updateNotification.tickerText = "开始下载"; updateNotification.setLatestEventInfo(this,apk_title,"0%",updatePendingIntent); //发出通知 updateNotificationManager.notify(0,updateNotification); //开启一个新的线程下载,如果使用Service同步下载,会导致ANR问题,Service本身也会阻塞 new Thread(new updateRunnable()).start();//这个是下载的重点,是下载的过程 return super.onStartCommand(intent, flags, startId);}private Handler updateHandler = new Handler(){ @Override public void handleMessage(Message msg) { switch(msg.what){ case DOWNLOAD_COMPLETE: //点击安装PendingIntent Uri uri = Uri.fromFile(updateFile); Intent installIntent = new Intent(Intent.ACTION_VIEW); installIntent.setDataAndType(uri, "application/vnd.android.package-archive"); updatePendingIntent = PendingIntent.getActivity(UpdateService.this, 0, installIntent, 0); updateNotification.defaults = Notification.DEFAULT_SOUND;//铃声提醒 updateNotification.setLatestEventInfo(UpdateService.this, FusionField.update_apk_title, "下载完成,点击安装。", updatePendingIntent); updateNotificationManager.notify(0, updateNotification); //停止服务 stopSelf(); break; case DOWNLOAD_FAIL: //下载失败 updateNotification.setLatestEventInfo(UpdateService.this, FusionField.update_apk_title, "下载失败。", updatePendingIntent); updateNotificationManager.notify(0, updateNotification); break; default: stopSelf(); } }};class updateRunnable implements Runnable { Message message = updateHandler.obtainMessage(); public void run() { message.what = DOWNLOAD_COMPLETE; try{ //增加权限; if(!updateDir.exists()){ updateDir.mkdirs(); } if(!updateFile.exists()){ updateFile.createNewFile(); } //下载函数 //增加权限; String strurl = strurl_apk; long downloadSize = downloadUpdateFile(strurl,updateFile); if(downloadSize>0){ //下载成功 updateHandler.sendMessage(message); } }catch(Exception ex){ ex.printStackTrace(); message.what = DOWNLOAD_FAIL; //下载失败 updateHandler.sendMessage(message); } }}public long downloadUpdateFile(String downloadUrl, File saveFile) throws Exception { int downloadCount = 0; int currentSize = 0; long totalSize = 0; int updateTotalSize = 0; HttpURLConnection httpConnection = null; InputStream is = null; FileOutputStream fos = null; try { URL url = new URL(downloadUrl); httpConnection = (HttpURLConnection)url.openConnection(); httpConnection.setRequestProperty("User-Agent", "PacificHttpClient"); if(currentSize > 0) { httpConnection.setRequestProperty("RANGE", "bytes=" + currentSize + "-"); } httpConnection.setConnectTimeout(10000); httpConnection.setReadTimeout(20000); updateTotalSize = httpConnection.getContentLength(); if (httpConnection.getResponseCode() == 404) { throw new Exception("fail!"); } is = httpConnection.getInputStream(); fos = new FileOutputStream(saveFile, false); byte buffer[] = new byte[4096]; int readsize = 0; while((readsize = is.read(buffer)) > 0){ fos.write(buffer, 0, readsize); totalSize += readsize; //为了防止频繁的通知导致应用吃紧,百分比增加10才通知一次,可自行调整 if((downloadCount == 0)||(int) (totalSize*100/updateTotalSize)-10>downloadCount){ downloadCount += 10; updateNotification.setLatestEventInfo(UpdateService.this, "正在下载", (int)totalSize*100/updateTotalSize+"%", updatePendingIntent); updateNotificationManager.notify(0, updateNotification); } } } finally { if(httpConnection != null) { httpConnection.disconnect(); } if(is != null) { is.close(); } if(fos != null) { fos.close(); } } return totalSize;}@Overridepublic IBinder onBind(Intent arg0) { // TODO Auto-generated method stub return null;}}
下载资源文件
和下载APK文件相同的是,都使用HttpDownLoader()方法,不同的是,下载资源文件一般是需要弹出等待进度条阻塞用户操作的。
- 弹出等待框,开始下载
private ProgressDialog pd; //等待下载滚动圈myRingtoneListView.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { currentSelected = position+1; // 下载更多 if(position >= ringtoneNum) { if(!isNetworkAvaiable()) { Toast.makeText(RingtoneActivity.this, "请确认网络连接正常!", Toast.LENGTH_SHORT).show(); return; } if(!FusionField.sdState.equals(Environment.MEDIA_MOUNTED)) { Toast.makeText(RingtoneActivity.this, "请插入SD卡!", Toast.LENGTH_SHORT).show(); return; } final int idToDownload = ringtoneNum+1; FusionField.downloader = new HttpDownLoader(); pd = ProgressDialog.show(RingtoneActivity.this, "正在下载", "请等待。。。",true, true); pd.setCanceledOnTouchOutside(false); pd.setOnCancelListener(new ProgressDialog.OnCancelListener() { @Override public void onCancel(DialogInterface dialog) { // 终止下载 pd.dismiss(); } }); new Thread(){ public void run(){ //在这里执行长耗时方法 int res = downloader.downLoadFile(ringtone_path+"/ringtone"+ idToDownload + ".mp3", "download/ringtone", "/ringtone" + idToDownload + ".mp3"); //执行完毕后给handler发送一个消息 if(res == 0) { handler.sendEmptyMessage(0); MainActivity main = MainActivity.getInstance(); } else if(res == 1) handler.sendEmptyMessage(1); else handler.sendEmptyMessage(3); } }.start(); return; }
- 下载成功或失败的消息处理
//定义Handler对象 private Handler handler =new Handler(){ @Override //当有消息发送出来的时候就执行Handler的这个方法 public void handleMessage(Message msg){ switch(msg.what) { case 0: // 下载成功 Toast.makeText(RingtoneActivity.this, "下载完成!", Toast.LENGTH_SHORT).show(); finish(); break; case 1: // 文件已存在 Toast.makeText(RingtoneActivity.this, "文件已存在!" , Toast.LENGTH_LONG).show(); break; case 2: // 下载被取消 Toast.makeText(RingtoneActivity.this, "已终止下载!", Toast.LENGTH_SHORT).show(); break; case 3: // 下载出错 Toast.makeText(RingtoneActivity.this, "下载中断,请检查网络设置", Toast.LENGTH_SHORT).show(); break; case 4: // 服务器地址出错 Toast.makeText(RingtoneActivity.this, "服务器地址解析错误,请检查网络设置", Toast.LENGTH_SHORT).show(); break; } super.handleMessage(msg); //只要执行到这里就关闭对话框 pd.dismiss(); } };
- * Android开发进阶系列(一) 序言 *
- * Android开发进阶系列(二) Tab页界面布局 *
- * Android开发进阶系列(三) 系统参数的获取和Broadcast *
- * Android开发进阶系列(四) 左移拉出Menu菜单界面布局 *
- * Android开发进阶系列(五) 连接服务器更新APK或下载资源文件 *
- * Android开发进阶系列(六) ListView的基本用法 *
- * Android开发进阶系列(七) 使用数据库 *
- * Android开发进阶系列(八) 界面美化之自定义弹出框 *
- * Android开发进阶系列(九) AChartEngine专题 *
0 0
- Android开发进阶系列(五) 连接服务器下载文件或资源
- Android开发进阶(五)--使用原始的XML文件
- Android开发进阶(五)----------SAX模式解析XML文件
- Android下载服务器资源文件(支持断点续传)
- hjr教程-Android(五):下载tomcat服务器文件
- android连接服务器下载文件工具类
- Android连接服务器,从服务器获取数据,以及从服务器下载文件(单,多线程)
- Android开发进阶系列(一) 序言
- Android多线程下载服务器资源
- Java连接FTP服务器,并上传或下载以及删除ftp服务器中的文件
- Android 从本地服务器下载文件与解析过程详解(五)
- android 开发环境资源下载
- Android开发 部分资源下载
- Android开发相关资源下载
- Android开发资源下载目录
- Android 开发资源连接地址
- Android 驱动开发系列五
- Android 驱动开发系列五
- iOS Plist解析(官方链接)
- C#获取文件当前路径
- oracle最重要的9个动态性能视图
- 车牌检测(定位)
- LC串联和并联电路汇总
- Android开发进阶系列(五) 连接服务器下载文件或资源
- 华为oj 整形数组合并
- Oracle数据字典详解
- WIFEXITED/WEXITSTATUS/WIFSIGNALED
- 【Android】adb mount挂载sdcard,删除垃圾app
- 软件破解注册码
- ios1学习总结
- 如何实现一个文件系统
- 一句shell命令搞定代码行数统计