Directory:

Mobile brain -SpringMVc RestFul background service (I) – environment construction

Mobile brain -SpringMVc build RestFul background service (2) – configure mysql database

Mobile brain -SpringMVc RestFul background service (III) -RestFul interface writing (simulating user registration and login)

Mobile brain -SpringMVc build RestFul backend service (4) – Add Token filter

Mobile brain -SpringMVc build RestFul background service (V) – Alipay payment

Mobile Brain -SpringMVc build RestFul background service (VI) – wechat Pay (Android)


Mobile brain -SpringMVc build RestFul background service (seven) – incremental update

Android Incremental Update (1) – Difference Files (Windows-Part1) Today’s blog post is a practical application of incremental updates. The incremental update is a differential file that is generated and saved according to the client version on the first access, so the first access is slightly slower and the subsequent access is faster:

First Visit:



Future visits:



See this effect is still good ~.


First, talk about the general business logic:

1. When the client (Android) checks the update, it will send the current APK MD5 value, version number, channel number and other information to the server;

2. When the server receives the version information of the client, it first searches the database according to the MD5 value, version number and channel number to see whether the corresponding subcontract has been generated. If there is a record, it directly returns the download address of the subcontract; Without record, the loop compares the APK packet whose MD5 value is equal to that of the client apK. This packet is the old APK packet, and then generates the difference packet of the new version of APK packet which is consistent with the channel. The corresponding lookup table is saved in the difference folder and the difference information is stored in the database and returned to the client. If there is no new package for the desired channel, there is no update.


Create and update entity classes and configuration data tables

2.1 update entity class updatebean.java (get and set methods added themselves)

[java]
view plain
copy
print
?

  1. package com.ywl5320.appservice.bean;  
  2.   
  3. / * *
  4.  * Created by ywl5320 on 2017/10/26. 
  5. * /
  6. public class UpdateBean extends BaseBean{  
  7.   
  8.     private Integer id;  
  9. / * *
  10. * old APK MD5 value
  11. * /
  12.     private String md5value;  
  13.   
  14. / * *
  15. * Old version number (code)
  16. * /
  17.     private Integer versioncode;  
  18.   
  19. / * *
  20. * Old version number (name)
  21. * /
  22.     private String versionName;  
  23.   
  24. / * *
  25. * New version number (Code)
  26. * /
  27.     private Integer newversioncode;  
  28.   
  29. / * *
  30. * New version number (name)
  31. * /
  32.     private String newversionName;  
  33.   
  34. / * *
  35. * Total file size
  36. * /
  37.     private Long filesize;  
  38.   
  39. / * *
  40. * Patch package size
  41. * /
  42.     private Long patchsize;  
  43.   
  44. / * *
  45. * Download address
  46. * /
  47.     private String downloadpath;  
  48.   
  49. / * *
  50. * Subcontract download address
  51. * /
  52.     private String patchdownloadpath;  
  53.   
  54. / * *
  55. * Channel identification
  56. * /
  57.     private String channelid;  
  58.   
  59.       
  60. }  
package com.ywl5320.appservice.bean; /** * Created by ywl5320 on 2017/10/26. */ public class UpdateBean extends BaseBean{ private Integer id; /** * old apk MD5 */ private String md5Value; /** * Old version number (code) */ private Integer versionCode; /** * Old version number (name) */ private String versionName; /** * New version number (code) */ private Integer newversionCode; /** * New version number (name) */ private String newversionName; /** * private Long filesize; /** * Patch size */ private Long patchsize; /** * download address */ private String downloadpath; /** ** * private String PatchDownloadPath; /** * private String channelId; }Copy the code


[html]
view plain
copy
print
?

  1. <class name=”com.ywl5320.appservice.bean.UpdateBean”  table=”t_update”>  
  2.         <id name=”id”  column=”id”>  
  3.             <generator class= “native”/>  
  4.         </id>  
  5.         <property name=”md5value”  column=”md5value”></property>  
  6.         <property name=”versioncode”  column=”versioncode”></property>  
  7.         <property name=”versionName”  column=”versionName”></property>  
  8.         <property name=”newversioncode”  column=”newversioncode”></property>  
  9.         <property name=”newversionName”  column=”newversionName”></property>  
  10.         <property name=”filesize”  column=”filesize”></property>  
  11.         <property name=”patchsize”  column=”patchsize”></property>  
  12.         <property name=”downloadpath”  column=”downloadpath”></property>  
  13.         <property name=”patchdownloadpath”  column=”patchdownloadpath”></property>  
  14.         <property name=”channelid”  column=”channelid”></property>  
  15.     </class>  
<class name="com.ywl5320.appservice.bean.UpdateBean" table="t_update">
        <id name="id" column="id">
            <generator class="native"/>
        </id>
        <property name="md5value" column="md5value"></property>
        <property name="versioncode" column="versioncode"></property>
        <property name="versionName" column="versionName"></property>
        <property name="newversioncode" column="newversioncode"></property>
        <property name="newversionName" column="newversionName"></property>
        <property name="filesize" column="filesize"></property>
        <property name="patchsize" column="patchsize"></property>
        <property name="downloadpath" column="downloadpath"></property>
        <property name="patchdownloadpath" column="patchdownloadpath"></property>
        <property name="channelid" column="channelid"></property>
    </class>Copy the code


3.1 The Updatedao. Java interface provides the ability to update, store, and delete update records

[java]
view plain
copy
print
?

  1. package com.ywl5320.appservice.dao;  
  2.   
  3. import com.ywl5320.appservice.bean.UpdateBean;  
  4.   
  5. / * *
  6.  * Created by ywl5320 on 2017/10/27. 
  7. * /
  8. public interface UpdateDao {  
  9.   
  10. / * *
  11. * Get updated information
  12.      * @param md5value 
  13.      * @param versioncode 
  14.      * @return 
  15. * /
  16.     UpdateBean getUpdateInfo(String md5value, int versioncode, String channelid);  
  17.   
  18. / * *
  19. * Store update information
  20.      * @param updateBean 
  21. * /
  22.     void saveUpdateInfo(UpdateBean updateBean);  
  23.   
  24. / * *
  25. * Delete updated information
  26.      * @param updateBean 
  27. * /
  28.     void deleteUpdateInfo(UpdateBean updateBean);  
  29.   
  30. }  
package com.ywl5320.appservice.dao; import com.ywl5320.appservice.bean.UpdateBean; /** * Created by ywl5320 on 2017/10/27. */ public interface UpdateDao {/** * @param md5Value * @param versioncode * @return */ UpdateBean getUpdateInfo(String md5value, int versioncode, String channelid); /** * Store update information * @param updateBean */ void saveUpdateInfo(updateBean); @param updateBean */ void deleteUpdateInfo(updateBean); }Copy the code




[java]
view plain
copy
print
?

  1. package com.ywl5320.appservice.dao;  
  2.   
  3. import com.ywl5320.appservice.bean.UpdateBean;  
  4. import org.springframework.orm.hibernate5.support.HibernateDaoSupport;  
  5.   
  6. import java.util.List;  
  7.   
  8. / * *
  9.  * Created by hlwky001 on 2017/10/27. 
  10. * /
  11. public class UpdateDaoImpl extends HibernateDaoSupport  implements UpdateDao {  
  12.   
  13.     public UpdateBean getUpdateInfo(String md5value, int versioncode, String channelid) {  
  14. List

    updates = (List

    ) this.getHibernateTemplate().find(“from UpdateBean where md5value=? and versioncode=? and channelid=?” , md5value, versioncode, channelid);

  15. if(updates ! = null && updates.size() > 0)
  16.         {  
  17.             return updates.get(0);  
  18.         }  
  19.         return null;  
  20.     }  
  21.   
  22.     public void saveUpdateInfo(UpdateBean updateBean) {  
  23.         this.getHibernateTemplate().save(updateBean);  
  24.     }  
  25.   
  26.     public void deleteUpdateInfo(UpdateBean updateBean) {  
  27.         this.getHibernateTemplate().delete(updateBean);  
  28.     }  
  29. }  
package com.ywl5320.appservice.dao; import com.ywl5320.appservice.bean.UpdateBean; import org.springframework.orm.hibernate5.support.HibernateDaoSupport; import java.util.List; /** * Created by hlwky001 on 2017/10/27. */ public class UpdateDaoImpl extends HibernateDaoSupport implements UpdateDao { public UpdateBean getUpdateInfo(String md5value, int versioncode, String channelid) { List<UpdateBean> updates = (List<UpdateBean>) this.getHibernateTemplate().find("from UpdateBean where md5value=? and versioncode=? and channelid=?" , md5value, versioncode, channelid); if(updates ! = null && updates.size() > 0) { return updates.get(0); } return null; } public void saveUpdateInfo(UpdateBean updateBean) { this.getHibernateTemplate().save(updateBean); } public void deleteUpdateInfo(UpdateBean updateBean) { this.getHibernateTemplate().delete(updateBean); }}Copy the code


Fourth, create the Service layer, which is also the focus

4.1 Update logic processing

1. Define the apK file naming rule: apkname_versioncode_versionname_channelID.apk. Such as: app_1_v1. 0.0 _xiaomi. Apk. This allows you to retrieve apK version information and channel information by name.

2. Create folder oldversion to store the oldversion of apk. Create folder newversion to store the newversion of apk. Create a folder patch to store the subcontracts generated by the old APK and the new APK.

3. When the apK information of the client is obtained, go through the oldVersion folder to find the MD5 value and find the APK consistent with the client; Then, according to the channel ID and version number of the client APK, find out whether there is a corresponding update package in the newVersion folder: if there is, generate the subpackage, return the download address of the subpackage and store the corresponding version information of the subpackage; Returns “Is the latest version” to the client if no.


4.2 add incremental update library Android Incremental Update (3) — Difference Files (Linux) — jar and.so library generated DLL or JAR package, such as:









Linux:

So repository location: / usr/dev/mylib BsDiffYwl5320. So

Add to environment variable:

[plain]
view plain
copy
print
?

  1. vim ~/.bashrc    
  2. export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/dev/mylib    
  3. source ~/.bashrc    
vim ~/.bashrc  
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/dev/mylib  
source ~/.bashrc  Copy the code


4.2 Generate patch package (PS: This is my logic, there can be better)

UpdateService.java

[java]
view plain
copy
print
?

  1. package com.ywl5320.appservice.service;  
  2.   
  3. import com.ywl5320.appservice.bean.RestFulBean;  
  4. import com.ywl5320.appservice.bean.UpdateBean;  
  5. import com.ywl5320.appservice.dao.UpdateDao;  
  6. import com.ywl5320.appservice.util.CommonUtils;  
  7. import com.ywl5320.appservice.util.RestFulUtil;  
  8. import com.ywl5320.bsdiff.BsDiffYwl5320Util;  
  9. import org.springframework.beans.factory.annotation.Autowired;  
  10. import org.springframework.transaction.annotation.Transactional;  
  11.   
  12. import java.io.File;  
  13.   
  14. / * *
  15.  * Created by ywl5320 on 2017/10/26. 
  16. * /
  17. @Transactional  
  18. public class UpdateService {  
  19.   
  20.     @Autowired  
  21.     private UpdateDao updateDao;  
  22.   
  23.     static String oldApksPath = “E:/source/oldversion”;  
  24.     static String newApkPath = “E:/source/newversion”;  
  25.     static String patchPath = “E:/source/patch”;  
  26.   
  27.     static  
  28.     {  
  29. If (commonutils.getosName ().contains(” Linux “))// Linux operating system
  30.         {  
  31.             oldApksPath = “/usr/dev/sources/oldversion”;  
  32.             newApkPath = “/usr/dev/sources/newversion”;  
  33.             patchPath = “/usr/dev/sources/patch”;  
  34.         }  
  35. Else if(CommonUtils.getosName (). Contains (” Windows “)) // Window operating system
  36.         {  
  37.             oldApksPath = “E:/source/oldversion”;  
  38.             newApkPath = “E:/source/newversion”;  
  39.             patchPath = “E:/source/patch”;  
  40.         }  
  41.     }  
  42.   
  43.     public RestFulBean<UpdateBean> checkUpdate(String md5value, int versioncode, String channelid){  
  44.   
  45.         UpdateBean updateBean = updateDao.getUpdateInfo(md5value, versioncode, channelid);  
  46. if(updateBean ! = null)
  47.         {  
  48.             File file = new File(patchPath + “/” + updateBean.getPatchdownloadpath());  
  49.             if(file.exists()) {  
  50. Return restfulUtil.getInstance ().getreSufulBean (updateBean, 0, “new version “);
  51.             }  
  52. // Todo does not exist to reproduce the delta package or delete this record
  53.             updateDao.deleteUpdateInfo(updateBean);  
  54. Return restfulUtil.getInstance ().getreSufulBean (null, 1, “No new version “);
  55.         }  
  56.         else  
  57.         {  
  58.             updateBean = createPatch(md5value, versioncode, channelid);  
  59. if(updateBean ! = null)
  60.             {  
  61.                 updateDao.saveUpdateInfo(updateBean);  
  62.                 UpdateBean updateBean1 = updateDao.getUpdateInfo(md5value, versioncode, channelid);  
  63. if(updateBean1 ! = null) {
  64.                     File file = new File(patchPath +  “/” + updateBean1.getPatchdownloadpath());  
  65.                     if(file.exists()) {  
  66. Return restfulUtil.getInstance ().getreSufulBean (updateBean1, 0, “new version “);
  67.                     }  
  68.                     updateDao.deleteUpdateInfo(updateBean1);  
  69. Return restfulUtil.getInstance ().getreSufulBean (null, 1, “No new version “);
  70.                 }  
  71.             }  
  72. Return restfulUtil.getInstance ().getreSufulBean (null, 1, “No new version “);
  73.         }  
  74.     }  
  75.   
  76.     private UpdateBean createPatch(String md5value, int versioncode, String channelid)  
  77.     {  
  78.   
  79.         File md5File = null;  
  80.         File newFile = null;  
  81.         String patchName = “”;  
  82.         File patchFile = null;  
  83.         String versionname = “”;  
  84.   
  85.         UpdateBean updateBean = null;  
  86.         int newVersionCode = 1;  
  87.         String newVersionName = “”;  
  88.   
  89.         File file = new File(oldApksPath);  
  90. if(! file.exists())
  91.             return null;  
  92.         File[] files = file.listFiles();  
  93.         if(files == null || files.length == 0)  
  94.             return null;  
  95.   
  96. / * *
  97. * Find the same version as the client based on the MD5 value
  98. * /
  99.         for(File f : files)  
  100.         {  
  101.             String fmd5 = CommonUtils.getFileMd5(f);  
  102.             if(fmd5.equals(md5value))  
  103.             {  
  104.                 System.out.print(f.getName() + ” md5: ” + fmd5);  
  105.                 String[] flag = f.getName().replace(“.apk”,  “”).split(“_”);  
  106. if(flag ! = null && flag.length == 4 && flag[3].equals(channelid))
  107.                 {  
  108.                     versionname = flag[2];  
  109.                     md5File = f;  
  110.                     break;  
  111.                 }  
  112.             }  
  113.         }  
  114.         if(md5File == null)  
  115.             return null;  
  116.   
  117. / * *
  118. * Get the latest version by channel
  119. * /
  120.         File nfile = new File(newApkPath);  
  121. if(! nfile.exists())
  122.             return null;  
  123.         File[] nfiles = nfile.listFiles();  
  124.         if(nfiles == null || nfiles.length ==  0)  
  125.             return null;  
  126.   
  127.         for(File nf : nfiles)  
  128.         {  
  129.             String[] flag = nf.getName().replace(“.apk”, “”).split( “_”);  
  130. if(flag ! = null && flag.length == 4 && flag[3].equals(channelid))
  131.             {  
  132. System.out.println(” channel: “+ channelId +” current latest version “+ nf.getName());
  133.                 newFile = nf;  
  134.                 newVersionCode = Integer.parseInt(flag[1]);  
  135.                 newVersionName = flag[2];  
  136.                 patchName = patchPath + “/” + nf.getName().replace( “.apk”, “”) + “_patch_” + versioncode + “.patch”;  
  137.                 break;  
  138.             }  
  139.         }  
  140.         if(newfile == null)  
  141.             return null;  
  142.   
  143.         System.out.println(“oldfile:” + md5File.getAbsolutePath());  
  144.         System.out.println(“newfile:” + newFile.getAbsolutePath());  
  145.         System.out.println(“patchfile:” + patchName);  
  146.   
  147.         int result = BsDiffYwl5320Util.getInstance().bsDiffFile(md5File.getAbsolutePath(), newFile.getAbsolutePath(), patchName);  
  148. if(result ! = 0)
  149.             return null;  
  150.   
  151.         patchFile = new File(patchName);  
  152. if(! patchFile.exists())
  153.             return null;  
  154.   
  155.         updateBean = new UpdateBean();  
  156.         updateBean.setMd5value(md5value);  
  157.         updateBean.setVersioncode(versioncode);  
  158.         updateBean.setVersionName(versionname);  
  159.         updateBean.setNewversioncode(newVersionCode);  
  160.         updateBean.setNewversionName(newVersionName);  
  161.         updateBean.setFilesize(md5File.length());  
  162.         updateBean.setPatchsize(patchFile.length());  
  163.         updateBean.setDownloadpath(newFile.getName());  
  164.         updateBean.setPatchdownloadpath(patchFile.getName());  
  165.         updateBean.setChannelid(channelid);  
  166.   
  167.         return updateBean;  
  168.     }  
  169.   
  170. }  
package com.ywl5320.appservice.service; import com.ywl5320.appservice.bean.RestFulBean; import com.ywl5320.appservice.bean.UpdateBean; import com.ywl5320.appservice.dao.UpdateDao; import com.ywl5320.appservice.util.CommonUtils; import com.ywl5320.appservice.util.RestFulUtil; import com.ywl5320.bsdiff.BsDiffYwl5320Util; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.annotation.Transactional; import java.io.File; /** * Created by ywl5320 on 2017/10/26. */ @Transactional public class UpdateService { @Autowired private UpdateDao updateDao; static String oldApksPath = "E:/source/oldversion"; static String newApkPath = "E:/source/newversion"; static String patchPath = "E:/source/patch"; Static {the if (CommonUtils getOsName (). The contains (" Linux ")) {/ / Linux operating system oldApksPath = "/ usr/dev/sources/oldversion"; newApkPath = "/usr/dev/sources/newversion"; patchPath = "/usr/dev/sources/patch"; } else if(commonUtils.getosName (). Contains (" Windows "))// Window operating system {oldApksPath = "E:/source/oldversion"; newApkPath = "E:/source/newversion"; patchPath = "E:/source/patch"; } } public RestFulBean<UpdateBean> checkUpdate(String md5value, int versioncode, String channelid){ UpdateBean updateBean = updateDao.getUpdateInfo(md5value, versioncode, channelid); if(updateBean ! = null) { File file = new File(patchPath + "/" + updateBean.getPatchdownloadpath()); If (file.exists()) {return restfulUtil.getInstance ().getresufulBean (updateBean, 0, "newer version "); } / / todo does not exist can reproduce the incremental package or delete this record updateDao. DeleteUpdateInfo (updateBean); Return restfulUtil.getInstance ().getreSufulBean (null, 1, "No new version "); } else { updateBean = createPatch(md5value, versioncode, channelid); if(updateBean ! = null) { updateDao.saveUpdateInfo(updateBean); UpdateBean updateBean1 = updateDao.getUpdateInfo(md5value, versioncode, channelid); if(updateBean1 ! = null) { File file = new File(patchPath + "/" + updateBean1.getPatchdownloadpath()); If (file.exists()) {return restfulUtil.getInstance ().getresufulBean (updateBean1, 0, "new version "); } updateDao.deleteUpdateInfo(updateBean1); Return restfulUtil.getInstance ().getreSufulBean (null, 1, "No new version "); }} return restfulUtil.getInstance ().getreSufulBean (null, 1, "no new version "); } } private UpdateBean createPatch(String md5value, int versioncode, String channelid) { File md5File = null; File newFile = null; String patchName = ""; File patchFile = null; String versionname = ""; UpdateBean updateBean = null; int newVersionCode = 1; String newVersionName = ""; File file = new File(oldApksPath); if(! file.exists()) return null; File[] files = file.listFiles(); if(files == null || files.length == 0) return null; */ for(File f: files) {String fmd5 = CommonUtils.getFilemd5 (f); /** * for(File f: files) {String fmd5 = CommonUtils.getFilemd5 (f); if(fmd5.equals(md5value)) { System.out.print(f.getName() + " md5: " + fmd5); String[] flag = f.getName().replace(".apk", "").split("_"); if(flag ! = null && flag.length == 4 && flag[3].equals(channelid)) { versionname = flag[2]; md5File = f; break; } } } if(md5File == null) return null; */ File nfile = new File(newApkPath); if(! nfile.exists()) return null; File[] nfiles = nfile.listFiles(); if(nfiles == null || nfiles.length == 0) return null; for(File nf : nfiles) { String[] flag = nf.getName().replace(".apk", "").split("_"); if(flag ! = null && flag.length == 4 && flag[3].equals(channelId)) {system.out.println (" channel: "+ channelId +" current latest version "+ nf.getName()); newFile = nf; newVersionCode = Integer.parseInt(flag[1]); newVersionName = flag[2]; patchName = patchPath + "/" + nf.getName().replace(".apk", "") + "_patch_" + versioncode + ".patch"; break; } } if(newfile == null) return null; System.out.println("oldfile:" + md5File.getAbsolutePath()); System.out.println("newfile:" + newFile.getAbsolutePath()); System.out.println("patchfile:" + patchName); int result = BsDiffYwl5320Util.getInstance().bsDiffFile(md5File.getAbsolutePath(), newFile.getAbsolutePath(), patchName); if(result ! = 0) return null; patchFile = new File(patchName); if(! patchFile.exists()) return null; updateBean = new UpdateBean(); updateBean.setMd5value(md5value); updateBean.setVersioncode(versioncode); updateBean.setVersionName(versionname); updateBean.setNewversioncode(newVersionCode); updateBean.setNewversionName(newVersionName); updateBean.setFilesize(md5File.length()); updateBean.setPatchsize(patchFile.length()); updateBean.setDownloadpath(newFile.getName()); updateBean.setPatchdownloadpath(patchFile.getName()); updateBean.setChannelid(channelid); return updateBean; }}Copy the code


[java]
view plain
copy
print
?

  1. package com.ywl5320.appservice.action;  
  2.   
  3. import com.ywl5320.appservice.bean.RestFulBean;  
  4. import com.ywl5320.appservice.bean.UpdateBean;  
  5. import com.ywl5320.appservice.bean.UserBean;  
  6. import com.ywl5320.appservice.service.UpdateService;  
  7. import org.springframework.beans.factory.annotation.Autowired;  
  8. import org.springframework.stereotype.Controller;  
  9. import org.springframework.web.bind.annotation.RequestMapping;  
  10. import org.springframework.web.bind.annotation.RequestMethod;  
  11. import org.springframework.web.bind.annotation.ResponseBody;  
  12.   
  13. / * *
  14.  * Created by ywl5320 on 2017/10/26. 
  15. * /
  16. @Controller  
  17. @RequestMapping(“/update”)  
  18. public class UpdateAction {  
  19.   
  20.     @Autowired  
  21.     private UpdateService updateService;  
  22.   
  23.     @ResponseBody  
  24.     @RequestMapping(value=”/checkupdate.do”, method= RequestMethod.GET)  
  25.     public RestFulBean<UpdateBean> loginByPwd(String md5value, int versioncode, String channelid)  
  26.     {  
  27.         System.out.println(“md5value:” + md5value);  
  28.         return updateService.checkUpdate(md5value, versioncode, channelid);  
  29.     }  
  30.   
  31. }  
package com.ywl5320.appservice.action;

import com.ywl5320.appservice.bean.RestFulBean;
import com.ywl5320.appservice.bean.UpdateBean;
import com.ywl5320.appservice.bean.UserBean;
import com.ywl5320.appservice.service.UpdateService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * Created by ywl5320 on 2017/10/26.
 */
@Controller
@RequestMapping("/update")
public class UpdateAction {

    @Autowired
    private UpdateService updateService;

    @ResponseBody
    @RequestMapping(value="/checkupdate.do", method= RequestMethod.GET)
    public RestFulBean<UpdateBean> loginByPwd(String md5value, int versioncode, String channelid)
    {
        System.out.println("md5value:" + md5value);
        return updateService.checkUpdate(md5value, versioncode, channelid);
    }

}
Copy the code


Six, test,

6.1 create a newversion of apk and put it in the newversion folder:




6.2. Place old apK in oldVersion folder:




6.3 Access Interface:



The server generates subcontracting.

Tomact Configure virtual paths.

Go to the conf folder in the tomact root directory and edit server.xml.

Add between <Host></Host> :

[plain]
view plain
copy
print
?

  1. <Context docBase=”E:\source\patch”  reloadable=”true”  debug=”0″ path=”apk/update/patch”/>  
<Context docBase="E:\source\patch"  reloadable="true"  debug="0" path="apk/update/patch"/>Copy the code




Eight, publish,

After the virtual path is configured in the previous step, you need to publish and restart Tomact to access it

8.1 Generating war package









8.2. Publish to Tomact

Copy the generated appService. war to the Tomact webapps folder:





8.3. Start TomAct

Bat command in the bin directory of tomact




8.4. Test download

Download address:

[plain]
view plain
copy
print
?

  1. http://192.168.1.138:8080/apk/update/patch/app_2_v1.0.1_xiaomi_patch_1.patch  
http://192.168.1.138:8080/apk/update/patch/app_2_v1.0.1_xiaomi_patch_1.patchCopy the code




OK, so incremental update is implemented, here is a Windows example, Linux principle is the same, configure tomact and mysql, add the.so environment variable and download the virtual address.

Client download using OKhttp3, here will not accept, otherwise a lot of screenshots and code, client complete code is also available on GitHub, you can download to see.


GitHub AppServiceRestFul