APK更新集成实践
任务目标:将内网APK打包后最新下载链接、更新时间、更改日志显示在一个我自己制作的APP里
任务作用:我们在内网测试时更新下载APK更加便捷,并且能够清楚目标APK的版本情况,回归、验证做到有的放矢
实现原理:
APK下载部分
使用Jenkins打包APK后执行shell将最新打包的APK复制到Nginx配置的根目录
cp -f $APK_BUILD_HOME/passenger-smzcself-release.apk /usr/local/nginx/html
Nginx配置:
/usr/local/nginx/conf/nginx.conf 添加一个9000端口的server
这样在网页上请求"http://192.168.3.151:9000/passenger-smzcself-release.apk"就可以下载都更新后的最新APK
APK更新时间部分
echo 更新时间 > /usr/local/nginx/html/passenger.html
echo $CURRENT_TIME >> /usr/local/nginx/html/passenger.html
shell将 APK打包时间写入到passenger.html文件,网页请求http://192.168.3.151:9000/passenger.html显示打包更新时间
APK更新日志部分
Jenkins每次打包成功后都会根据git或者svn提交注释生成修改日志
这个变更日志保存在Jenkins工作文件夹jobs下builds/lastSuccessfulBuild/changelog.xml里面,这个文件的XML格式,我需要将它简单切割后内容发送到/usr/local/nginx/html/passenger_log.html,最终访问http://192.168.3.151:9000/passenger_log.html这个页面就可以显示我们的APK上一次打包更新到了什么内容
切割脚本如下:
1 #!/bin/sh 2 function funAWK() 3 { 4 out=`awk '/./ {print}' $1` 5 out1=`echo $out | awk ' 6 { 7 alen=split($0,a,"committer"); 8 for(k=2;k<=alen;k++) 9 { 10 print a[k]; 11 } 12 }'` 13 echo "$out1" > 001.log 14 out2=`cat 001.log | while read line 15 do 16 echo ${line%%100*} 17 done` 18 echo "$out2" > 001.log 19 out3=`cat 001.log | while read line 20 do 21 echo ${line%%This reverts*} 22 done` 23 echo "$out3" > 001.log 24 out4=`cat 001.log | while read line 25 do 26 echo ${line%%Change-Id*} 27 done` 28 echo "$out4" > 001.log 29 sed -i "s/+0800/提交/g" 001.log 30 cat 001.log > $2 31 } 32 funAWK /var/lib/jenkins/jobs/Android_Passenger_Release/builds/lastSuccessfulBuild/changelog.xml /usr/local/nginx/html/passenger_log.html 33 funAWK /var/lib/jenkins/jobs/Android_Taxi_Driver_Release/builds/lastSuccessfulBuild/changelog.xml /usr/local/nginx/html/taxi_log.html 34 funAWK /var/lib/jenkins/jobs/Android_Driver_Release/builds/lastSuccessfulBuild/changelog.xml /usr/local/nginx/html/driver_log.html
最终集成
我将这几个网页集成在同一个网页上一个网页显示下载链接另外两个网页作为整个网页的iframe显示,创建一个APP工程,这个工程非常的简单只有一个webview控件,这个控件显示了我制作了的那个网页,更新APK信息后在APP端只用下拉刷新网页就会显示最新的更新信息
最终效果
安卓布局代码:
1 <?xml version="1.0" encoding="utf-8"?> 2 <manifest xmlns:android="http://schemas.android.com/apk/res/android" 3 package="com.example.smzc_apk_update"> 4 <uses-permission android:name="android.permission.INTERNET"></uses-permission> 5 <application 6 android:allowBackup="true" 7 android:icon="@mipmap/smzc" 8 android:label="神马APK升级" 9 android:roundIcon="@mipmap/smzc" 10 android:supportsRtl="true" 11 android:usesCleartextTraffic="true" 12 android:theme="@style/AppTheme"> 13 <activity android:name=".MainActivity"> 14 <intent-filter> 15 <action android:name="android.intent.action.MAIN" /> 16 17 <category android:name="android.intent.category.LAUNCHER" /> 18 </intent-filter> 19 </activity> 20 21 </application> 22 </manifest>
操作代码:
1 package com.example.smzc_apk_update; 2 3 import android.os.Handler; 4 import android.support.v4.widget.SwipeRefreshLayout; 5 import android.support.v7.app.AppCompatActivity; 6 import android.os.Bundle; 7 import android.webkit.WebView; 8 9 public class MainActivity extends AppCompatActivity { 10 private WebView webview; SwipeRefreshLayout swipeRefreshLayout; 11 @Override 12 protected void onCreate(Bundle savedInstanceState) { 13 super.onCreate( savedInstanceState ); 14 setContentView( R.layout.activity_main ); 15 webview = (WebView) findViewById( R.id.webView ); 16 webview.loadUrl( "http://192.168.3.151:9000/" ); 17 swipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh_layout); 18 //重写这个布局的下拉功能 19 swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { 20 @Override 21 public void onRefresh() { 22 webview.clearCache( true); 23 //webview.reload(); 24 webview.loadUrl( "http://192.168.3.151:9000/" ); 25 new Handler().postDelayed(new Runnable() { 26 @Override 27 public void run() { 28 swipeRefreshLayout.setRefreshing(false); 29 } 30 }, 31 2000); 32 } 33 }); 34 } 35 }
结语
又到了大家喜闻乐见的血泪总结时间,本次任务耗时4天,其中对更改日志的切割耗时1天半,总结的坑点如下:
1.在shell脚本中 echo $a 和echo “$a” 是不一样的,不加引号时输出会自动合并到一行里,我反反复复在这个问题里面饶了1天才明白过来
2.在安卓里
23 //webview.reload();
24 webview.loadUrl( "http://192.168.3.151:9000/" );是不一样的,
webview.reload()不会刷新 网页的iframe