android APP实现更新 PHP后台服务器
android APP实现更新 PHP后台服务器
最近自己在做一款APP,需要实现APP版本更新功能,从网上找了许多资料,只找到了关于移动端的实现。经过我的研究,终于实现了比较完整的android APP版本更新功能,在此分享给广大朋友,但是我的ios端还没实现,但是传输是基于的http协议,实现原理应该是大同小异的。接下来进入正文。
PHP后台服务器实现
后台的实现是基于的thinkPHP框架。对于PHP开发框架thinkPHP框架的朋友,只要去官网下载手册,看那么几页,我想你应该就懂了。
接下来直接给出PHP代码实现。
对于这个文件,大家需要修改的便是命名空间。
namespace API\Controller; use Think\Controller;
至于为什么,大家需要了解下PHP的基础知识,和thinkPHP框架的开发流程就可以了,很快的。
<?php namespace API\Controller; use Think\Controller; class ServerController extends Controller { public function index(){ //$this->show('<style type="text/css">*{ padding: 0; margin: 0; } div{ padding: 4px 48px;} body{ background: #fff; font-family: "寰蒋闆呴粦"; color: #333;font-size:24px} h1{ font-size: 100px; font-weight: normal; margin-bottom: 12px; } p{ line-height: 1.8em; font-size: 36px }</style><div style="padding: 24px 48px;"> <h1>:)</h1><p>娆㈣繋浣跨敤 <b>ThinkPHP</b>锛?/p><br/>[ 鎮ㄧ幇鍦ㄨ闂殑鏄疕ome妯″潡鐨処ndex鎺у埗鍣?]</div><script type="text/javascript" src="http://tajs.qq.com/stats?sId=9347272" charset="UTF-8"></script>','utf-8'); echo "hello"; } function updateInfo(){ $result=array( 'version'=>'1.0', 'description'=>'目前已经更新了卡屏功能', 'url'=>'http://localhost/index.php/API/Server/download' ); echo json_encode($result); } function download(){ $file = "/tmp/test.apk"; $filename = basename($file);//返回路径中的文件名部分。 /* * header() 函数向客户端发送原始的 HTTP 报头。 * 必须在任何实际的输出被发送之前调用 header() 函数 * */ header("Content-type: application/octet-stream"); //处理中文文件名 $ua = $_SERVER["HTTP_USER_AGENT"]; $encoded_filename = rawurlencode($filename); if (preg_match("/MSIE/", $ua)) { header('Content-Disposition: attachment; filename="' . $encoded_filename . '"'); } else if (preg_match("/Firefox/", $ua)) { header("Content-Disposition: attachment; filename*=\"utf8''" . $filename . '"'); } else { header('Content-Disposition: attachment; filename="' . $filename . '"'); } header("Content-Length: ". filesize($file)); /* * readfile() 函数输出一个文件。 * 该函数读入一个文件并写入到输出缓冲。 * 若成功,则返回从文件中读入的字节数。若失败,则返回 false。 */ ob_clean(); flush(); readfile($file); } }
这里需要解释的是
function updateInfo()
function download(){
new Thread() { public void run() { HttpClient client = new DefaultHttpClient(); HttpGet get = new HttpGet(url); HttpResponse response; try { response = client.execute(get); HttpEntity entity = response.getEntity(); int length = (int) entity.getContentLength(); progressDialog.setMax(length); InputStream is = entity.getContent(); FileOutputStream fileOutputStream = null; if (is != null) { File file = new File( Environment.getExternalStorageDirectory(), "Test.apk"); fileOutputStream = new FileOutputStream(file); byte[] buf = new byte[10]; int ch = -1; int process = 0; while ((ch = is.read(buf)) != -1) { fileOutputStream.write(buf, 0, ch); process += ch; progressDialog.setProgress(process); } } fileOutputStream.flush(); if (fileOutputStream != null) { fileOutputStream.close(); } down(); } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }.start();
而PHP的实现代码是download中的
ob_clean(); flush(); readfile($file);
至于底层的原理是,readfile方法封装了,http文件传输的基本实现,大家可以百度下,以上两段代码配合,一个客户端,一个服务器,就能够实现基于http文件的传输.
import android.annotation.SuppressLint; import android.app.Activity; import android.app.AlertDialog; import android.app.ProgressDialog; import android.content.DialogInterface; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.os.Message; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.Toast; import com.example.administrator.dongzhiwuapp.R; public class SetActivity extends Activity { private UpdateInfo info; private ProgressDialog progressDialog;//下载进度条窗口 UpdateInfoService updateInfoService; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.update); Button button=(Button)findViewById(R.id.button1); button.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { checkUpdate(); } }); } private void checkUpdate(){ new Thread() { public void run() { try { updateInfoService = new UpdateInfoService(SetActivity.this); info = updateInfoService.getUpDateInfo(); handler1.sendEmptyMessage(0); } catch (Exception e) { e.printStackTrace(); } }; }.start(); } @SuppressLint("HandlerLeak") private Handler handler1 = new Handler() { public void handleMessage(Message msg) { if (updateInfoService.isNeedUpdate()) { showUpdateDialog(); } } }; private void showUpdateDialog() { AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setIcon(android.R.drawable.ic_dialog_info); builder.setTitle("请升级APP版本至" + info.getVersion()); builder.setMessage(info.getDescription()); builder.setCancelable(false); builder.setPositiveButton("确定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { if (Environment.getExternalStorageState().equals( Environment.MEDIA_MOUNTED)) { downFile(info.getUrl()); } else { Toast.makeText(SetActivity.this, "SD卡不可用,请插入SD卡", Toast.LENGTH_SHORT).show(); } } }); builder.setNegativeButton("取消", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { } }); builder.create().show(); } //进入下载 void downFile(final String url) { progressDialog = new ProgressDialog(SetActivity.this); progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); progressDialog.setTitle("正在下载"); progressDialog.setMessage("请稍后..."); progressDialog.setProgress(0); progressDialog.show(); updateInfoService.downLoadFile(url, progressDialog,handler1); } }
import android.annotation.SuppressLint; import android.app.Activity; import android.app.AlertDialog; import android.app.ProgressDialog; import android.content.DialogInterface; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.os.Message; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.Toast; import com.example.administrator.dongzhiwuapp.R; public class SetActivity extends Activity { private UpdateInfo info; private ProgressDialog progressDialog;//下载进度条窗口 UpdateInfoService updateInfoService; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.update); Button button=(Button)findViewById(R.id.button1); button.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { checkUpdate(); } }); } private void checkUpdate(){ new Thread() { public void run() { try { updateInfoService = new UpdateInfoService(SetActivity.this); info = updateInfoService.getUpDateInfo(); handler1.sendEmptyMessage(0); } catch (Exception e) { e.printStackTrace(); } }; }.start(); } @SuppressLint("HandlerLeak") private Handler handler1 = new Handler() { public void handleMessage(Message msg) { if (updateInfoService.isNeedUpdate()) { showUpdateDialog(); } } }; private void showUpdateDialog() { AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setIcon(android.R.drawable.ic_dialog_info); builder.setTitle("请升级APP版本至" + info.getVersion()); builder.setMessage(info.getDescription()); builder.setCancelable(false); builder.setPositiveButton("确定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { if (Environment.getExternalStorageState().equals( Environment.MEDIA_MOUNTED)) { downFile(info.getUrl()); } else { Toast.makeText(SetActivity.this, "SD卡不可用,请插入SD卡", Toast.LENGTH_SHORT).show(); } } }); builder.setNegativeButton("取消", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { } }); builder.create().show(); } //进入下载 void downFile(final String url) { progressDialog = new ProgressDialog(SetActivity.this); progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); progressDialog.setTitle("正在下载"); progressDialog.setMessage("请稍后..."); progressDialog.setProgress(0); progressDialog.show(); updateInfoService.downLoadFile(url, progressDialog,handler1); } }
/** * 获取服务器地址 */ public class GetServerUrl{ static String url="http://"; public static String getUrl() { return url; } }
/* * * 版本更新信息类 * 1、获取版本字符串信息 * 2、设置版本字符串信息 * 3、获取版本描述 * 4、设置版本描述 * 5、获取URL地址 * 6、设置URL地址 * */ public class UpdateInfo { private String version; private String description; private String url; public String getVersion() { return version; } public void setVersion(String version) { this.version = version; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } }
import android.app.ProgressDialog; import android.content.Context; import android.content.Intent; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.net.Uri; import android.os.Environment; import android.os.Handler; import android.util.Log; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.util.EntityUtils; import org.json.JSONObject; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; public class UpdateInfoService { ProgressDialog progressDialog; Handler handler; Context context; UpdateInfo updateInfo; public UpdateInfoService(Context context){ this.context=context; } /* * 获取更新信息 * 版本信息存储在服务器的update.txt文件中 * 更新信息包括: * 1、版本信息 * 2、最新版本具体描述 * 3、下载地址 * * */ public UpdateInfo getUpDateInfo() throws Exception { HttpClient httpClient = new DefaultHttpClient(); HttpGet httpGet = new HttpGet("http://localhost/index.php/API/Server/updateInfo"); HttpResponse httpResponse = httpClient.execute(httpGet); UpdateInfo updateInfo = new UpdateInfo(); if (httpResponse.getStatusLine().getStatusCode() == 200)//请求相应成功 { HttpEntity entity = httpResponse.getEntity(); String response = EntityUtils.toString(entity, "utf-8"); JSONObject jsonObject=new JSONObject(response); Log.d("dsdsada", "getUpDateInfo: "+response); updateInfo.setVersion(jsonObject.getString("version")); updateInfo.setDescription(jsonObject.getString("description")); updateInfo.setUrl(jsonObject.getString("url")); this.updateInfo = updateInfo; return updateInfo; } updateInfo.setVersion(""); updateInfo.setDescription(""); updateInfo.setUrl(""); this.updateInfo = updateInfo; return updateInfo; } /* *判断是否需要更新 */ public boolean isNeedUpdate(){ String new_version = updateInfo.getVersion(); String now_version=""; try { PackageManager packageManager = context.getPackageManager(); PackageInfo packageInfo = packageManager.getPackageInfo( context.getPackageName(), 0); now_version= packageInfo.versionName; } catch (NameNotFoundException e) { e.printStackTrace(); } if (new_version.equals(now_version)) { return false; } else { return true; } } /* * * 下载文件 * */ public void downLoadFile(final String url,final ProgressDialog pDialog,Handler h){ progressDialog=pDialog; handler=h; new Thread() { public void run() { HttpClient client = new DefaultHttpClient(); HttpGet get = new HttpGet(url); HttpResponse response; try { response = client.execute(get); HttpEntity entity = response.getEntity(); int length = (int) entity.getContentLength(); progressDialog.setMax(length); InputStream is = entity.getContent(); FileOutputStream fileOutputStream = null; if (is != null) { File file = new File( Environment.getExternalStorageDirectory(), "Test.apk"); fileOutputStream = new FileOutputStream(file); byte[] buf = new byte[10]; int ch = -1; int process = 0; while ((ch = is.read(buf)) != -1) { fileOutputStream.write(buf, 0, ch); process += ch; progressDialog.setProgress(process); } } fileOutputStream.flush(); if (fileOutputStream != null) { fileOutputStream.close(); } down(); } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }.start(); } //下载完毕,退出下载,进入安装APP步骤 void down() { handler.post(new Runnable() { public void run() { progressDialog.cancel(); update(); } }); } //安装最新版本APP void update() { Intent intent = new Intent(Intent.ACTION_VIEW); intent.setDataAndType(Uri.fromFile(new File(Environment .getExternalStorageDirectory(), "Test.apk")), "application/vnd.android.package-archive"); context.startActivity(intent); } }
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Linux_开发工具
Linux_开发工具 01 除了vim, 还有哪些常用的牛逼的编辑器, 并能够横向对比编辑器之间的区别和优缺点. Emacs 如果说Vim是编辑器之神,那么Emacs是神的编辑器。 有句夸张的话说:Emacs是伪装成编辑器的操作系统,这句话并不夸张。 Emacs其实是个Lisp的解释器,因此可以用Lisp灵活地扩展。 Lisp是什么东西,这同样是种很有生命力的编程语言。在C语言还没有发明的年代,MIT的人工智能实验室写ITS操作系统时,一部分用的是汇编语言,还有一部分就是用的Lisp。 现在,Lisp仍在人工智能研究领域广泛使用着。有这么牛逼的扩展语言,注定Emacs向着无所不能的方向发展。渐渐地,人们用Emacs不再限于写程序,写文档,而且在Emacs里管理文件系统,运行终端,收邮件,上网,听音乐……,真是一发不可收拾。甚至,有人用Emacs控制咖啡机煮咖啡。 在基于编辑器的功能基础上,Emacs有如下特点: (1)交互式编辑器(2)实时编辑器(3)高级编辑器(4)自文档化(5)可定制性(6)可扩展性(集成Lisp语言)(7)支持X Window环境 Emacs和vim的区别: (1...
- 下一篇
【Java EE】从零开始写项目【总结】
从零开发项目概述 最近这一直在复习数据结构和算法,也就是前面发出去的排序算法八大基础排序总结,Java实现单向链表,栈和队列就是这么简单,十道简单算法题等等... 被虐得不要不要的,即使是非常简单有时候绕半天,想不明白。 本来这篇博文是想留到我最后Java基础复习完再写出来的,鉴于公众号有的同学想看看邮箱登陆的案例,想看看Java开发后台是怎么的,于是我就提前写了这篇博文 这个项目是我自己手写的第一个SSM项目(毕竟学了当然得搞点事情,对吧),是上年写的小东西。当然了,现在回过头去看这个项目是有很多的不足的,仅供参考。用的也不是新技术,只是把我之前当时所学的一些东西做一个总结...如果想学新知识的同学看到这里就可以留步啦~ 所以说,你可能会看到比较旧的技术,写得不好的地方都会有~如果是写过项目的同学而言,这个仅仅是一个Demo。对于没写过项目的同学可以适当的参考一下,因为用的是非常简单的技术,都是耳熟能详的技术,不会有什么难懂的地方~ PS:希望各位大佬不要攻击它,我没有做任何的安全措施。即使留了评论的功能,XSS攻击防范也没做,请手下留情啊~ 地址: 预览:http://www.zh...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Eclipse初始化配置,告别卡顿、闪退、编译时间过长
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- SpringBoot2整合Thymeleaf,官方推荐html解决方案
- SpringBoot2整合Redis,开启缓存,提高访问速度
- CentOS8编译安装MySQL8.0.19
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- CentOS7,8上快速安装Gitea,搭建Git服务器
- Docker安装Oracle12C,快速搭建Oracle学习环境
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- Windows10,CentOS7,CentOS8安装Nodejs环境