博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
android APP实现更新 PHP后台服务器
阅读量:6096 次
发布时间:2019-06-20

本文共 15729 字,大约阅读时间需要 52 分钟。

android APP实现更新 PHP后台服务器

最近自己在做一款APP,需要实现APP版本更新功能,从网上找了许多资料,只找到了关于移动端的实现。经过我的研究,终于实现了比较完整的android APP版本更新功能,在此分享给广大朋友,但是我的ios端还没实现,但是传输是基于的http协议,实现原理应该是大同小异的。接下来进入正文。

PHP后台服务器实现

后台的实现是基于的thinkPHP框架。对于PHP开发框架thinkPHP框架的朋友,只要去官网下载手册,看那么几页,我想你应该就懂了。

接下来直接给出PHP代码实现。

对于这个文件,大家需要修改的便是命名空间。

namespace API\Controller;use Think\Controller;

至于为什么,大家需要了解下PHP的基础知识,和thinkPHP框架的开发流程就可以了,很快的。

show('

:)

娆㈣繋浣跨敤 ThinkPHP锛?/p>

[ 鎮ㄧ幇鍦ㄨ闂殑鏄疕ome妯″潡鐨処ndex鎺у埗鍣?]

','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()
这个方法实现的是获得最近的版本信息。然后和移动端进行匹配
URL地址是:http://localhost/index.php/API/Server/updateinfo,大家可以根据自己的服务器或者云服务器的IP地址进行修改。
 
function download(){
这个方法实现的是下载功能,也就是核心方法。移动端需要访问到这个IP地址才能进行文件的下载。
URL地址是:http://localhost/index.php/API/Server/download,大家可以根据自己的服务器或者云服务器的IP地址进行修改。
 
关于需要下载的文件路径,我是存放在ubuntu系统的/tmp目录下的
 
android移动端实现
 
移动端我直接给出了实现放的类和方法以及活动,就不解释了。
只给出基本的原理
1、从这个URL地址http://localhost/index.php/API/Server/updateinfo获取最新的版本信息,通过http协议和json协议解析出基本的版本信息,然后存储在UpdateInfo类中,然后和APP的当前版本进行比较,如果有最新版则下载。
2、关于下载,android端的核心实现代码是
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文件的传输.

 
最后给出android端的代码
 
 
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);   }   }
 
github项目地址:https://github.com/huanghuaisong/android-php-appUpdate/
原文地址

转载地址:http://sawza.baihongyu.com/

你可能感兴趣的文章
JS之原生JS获取表单得所有值
查看>>
JDBC Driver接口连接数据库,实际开发基本不用
查看>>
Golang 中的并发限制与超时控制
查看>>
【Tip】如何让引用的dll随附的xml注释文档、pdb调试库等文件不出现在项目输出目录中...
查看>>
数据填报修改时如何增加操作人员信息
查看>>
WPF InkCanvas 毛笔效果
查看>>
BugHD 新功能-更灵活的崩溃收集、更精准的崩溃定位
查看>>
lua 调用 dll 的简单demo
查看>>
Electron 5.0.0 发布
查看>>
基于Django实现 RESTful API 之RestFramework框架1
查看>>
下一步瞄准室内,u-blox厘米级高精定位为自动驾驶铺路
查看>>
Kodi 基金会加入 Linux 基金会,帮助发展开源运动
查看>>
Linux下用户的创建与删除
查看>>
python3中的进程
查看>>
[LeetCode]1-bit and 2-bit Characters 1位和2位字符
查看>>
[网络基础] Web请求与响应
查看>>
锋利 RAM 合集
查看>>
Python Vs R:数据科学家的永恒问题
查看>>
redis 学习指南
查看>>
探索Redis设计与实现10:Redis的事件驱动模型与命令执行过程
查看>>