ionic3 實現app版本更新下載並開啟進行安裝(包括android7+無法自動安裝apk問題的解決方法)
阿新 • • 發佈:2018-11-01
記錄一下實現app版本一鍵更新下載的功能。
我的專案的總體的檔案:
使用的外掛列表如下:
需要純實現該功能用到的基本上是除了後三個。
首先,安裝這些外掛,在app.component.ts頁面上加入
import { Component, ViewChild } from '@angular/core';
import { Platform, ToastController, Nav, IonicApp } from 'ionic-angular';
import { StatusBar } from '@ionic-native/status-bar';
import { SplashScreen } from '@ionic-native/splash-screen';
import { AppVersion } from '@ionic-native/app-version';
import { SharedDataService } from "./../providers/SharedDataService";
import { File } from '@ionic-native/file';
import { Device } from '@ionic-native/device';
import { HomeService } from "./../pages/home/HomeService" ;
declare var cordova: any;
@Component({
templateUrl: 'app.html',
providers: [ Device,AppVersion,HomeService,File ]
})
export class MyApp {
rootPage:any = "AdvertPage";
backButtonPressed: boolean = false; //用於判斷返回鍵是否觸發
@ViewChild('myNav') nav: Nav;
constructor(
private device : Device,
public ionicApp: IonicApp,
private appVersion: AppVersion,
private file: File,
public platform: Platform,
public statusBar: StatusBar,
public toastCtrl: ToastController,
splashScreen: SplashScreen,
private homeService: HomeService,
private Share: SharedDataService) {
/*SharedDataService是一個存放公共變數的地方
*
*/
platform.ready().then(() => {
/*儲存版本資訊及判斷儲存路徑開始*/
// 讀取所用的平臺
//獲取當前平臺資訊 this.device.platform
this.appVersion.getVersionNumber().then(data => {
//當前app版本號 data,儲存該版本號
this.Share.appVersion = data;
}, error => console.error(error => {
//獲取當前版本號失敗進行的操作
}));
this.appVersion.getPackageName().then(data => {
//當前應用的packageName:data,儲存該包名
this.Share.packageName = data;
}, error => console.error(error => {
//獲取該APP id 失敗
}));
this.Share.platform = this.device.platform;
this.Share.savePath = this.Share.platform == 'iOS' ? this.file.documentsDirectory : this.file.externalDataDirectory;
//儲存的沙盒地址:this.Share.savePath
/*儲存版本資訊及判斷儲存路徑結束*/
});
}
//提示彈窗
alertToast(msg){
let toast = this.toastCtrl.create({
message: msg,
cssClass:'detailToast',
duration: 2000
});
toast.present();
}
}
傳送獲取app資訊介面的請求寫在:
public getUpdateInfo(uuid, showLoading) {
if (showLoading) {
this.loading.presentLoadingDefault();
}
var url = "此地址獲取app資訊的介面地址" + uuid;//此處是我們專案介面所需把本地app的資訊包名傳到介面
return this.http.get(url).toPromise()
.then(res => {
if (this.loading) {
this.loading.dismissLoadingDefault();
}
return res.json();
})
.catch(err => {
this.handleError(err);
});
}
在相應的service(MeService.ts)裡面寫這樣的方法:
getUpdate(showLoading: boolean) {
return this.httpService.getUpdateInfo(this.Share.packageName, showLoading);
}
在需要的頁面me.ts檔案中程式碼如下,然後在頁面中直接呼叫update()方法即可:
import { Component, ViewChild } from '@angular/core';
import { NavController,IonicPage,ActionSheetController,AlertController } from 'ionic-angular';
import { SharedDataService } from "./../../providers/SharedDataService";
import { App,ViewController } from 'ionic-angular';
import { MeService } from "./MeService";
import { FileTransfer, FileTransferObject } from '@ionic-native/file-transfer';
import { FileOpener } from '@ionic-native/file-opener';
import { LoadingService } from "./../../providers/LoadingService";
@IonicPage()
@Component({
selector: 'page-me',
templateUrl: 'me.html',
providers: [FileOpener, FileTransfer, AlertController, MeService]
})
export class MePage {
constructor(public navCtrl: NavController,
public Share: SharedDataService,
private app:App,
private fileOpener: FileOpener,
private transfer: FileTransfer,
// private file: File,
private alertCtrl: AlertController,
private loadingService: LoadingService,
public actionSheetCtrl: ActionSheetController,
private meService: MeService,
public viewCtrl: ViewController) {
}
//退出到登入頁
exitTo(){
this.app.getRootNav().setRoot("LoginPage");
delete (<any>window).launchURL;
}
update() {
this.meService.getUpdate(true).then(data => {
console.log(data);
// 判斷當前版本號否大於伺服器的版本號
var serveVersion = data && data.appList && data.appList.group && data.appList.group.app && data.appList.group.app.version;
console.log(serveVersion);
console.log(this.Share.appVersion);
if (this.versionfunegt(serveVersion, this.Share.appVersion)) {
console.log("檢查到新版本,是否更新APP");
let alert1 = this.alertCtrl.create({
title: '版本更新',
message: '檢查到最新版本,是否進行更新',
buttons: [
{
text: '否',
role: 'cancel',
handler: () => {
console.log('不進行更新');
}
},
{
text: '是',
handler: () => {
console.log('更新APP');
var url = data && data.appList && data.appList.group && data.appList.group.app && data.appList.group.app.url;
console.log(url);
if (this.Share.platform == 'iOS') {
console.log('開啟iOS下載地址----------------------------');
window.location.href = 'itms-services://?action=download-manifest&url=' + url;
} else {
console.log('開始下載Android程式碼----------------------------');
const fileTransfer: FileTransferObject = this.transfer.create();
fileTransfer.onProgress(progressEvent => {
var present = new Number((progressEvent.loaded / progressEvent.total) * 100);
console.log('當前進度為:' + present.toFixed(0));
var presentInt = present.toFixed(0);
this.loadingService.presentProgress(presentInt);
});
var savePath = this.Share.savePath + 'android.apk';
fileTransfer.download(encodeURI(url), savePath).then((entry) => {
console.log('儲存apk包的地址為: ' + this.Share.savePath + 'Ceshiname.apk');
console.log('download complete: ' + entry.toURL());
console.log("下載成功");
this.fileOpener.open(entry.toURL(), "application/vnd.android.package-archive")
.then(() => console.log('開啟apk包成功!'))
.catch(e => console.log('開啟apk包失敗!', e));
}, (error) => {
console.log("下載失敗");
this.loadingService.presentTip('操作提醒', '由於部分手機出現異常,請您進入手機設定-應用管理-Ceshiname-許可權,將儲存許可權開啟後再進行升級,由此給您帶來的不便,敬請諒解。');
for(var item in error) {
console.log(item + ":" + error[item]);
}
});
}
}
}
]
});
alert1.present();
} else {
this.loadingService.presentMsg("已是最新版本!");
}
});
}
// 比較版本號
versionfunegt (a, b) {
var _a = this.toNum(a), _b = this.toNum(b);
if(_a == _b) {
console.log("版本號相同!版本號為:"+a);
return false;
} else if(_a > _b) {
console.log("版本號"+a+"是新版本!");
return true;
} else {
console.log("版本號"+b+"是新版本!");
return false;
}
}
toNum (a) {
var a = a.toString();
//也可以這樣寫 var c=a.split(/\./);
var c = a.split('.');
var num_place = ["","0","00","000","0000"], r = num_place.reverse();
for (var i = 0; i< c.length; i++){
var len = c[i].length;
c[i] = r[len] + c[i];
}
var res = c.join('');
return res;
}
//字型
changeFont() {
let actionSheet = this.actionSheetCtrl.create({
title: '設定字型大小',
buttons: [
{
text: '小',
role: 'destructive',
handler: () => {
this.Share.fontSize = 'small';
}
},
{
text: '中',
handler: () => {
this.Share.fontSize = 'normal';
}
},{
text: '大',
handler: () => {
this.Share.fontSize = 'large';
}
},
{
text: '取消',
role: 'cancel',
handler: () => {
console.log('Cancel clicked');
}
}
]
});
actionSheet.present();
}
}
公共變數的存放區域為SharedDataService.ts:
import { Injectable } from '@angular/core';
import { HttpService } from "./HttpService";
import { LoadingService } from "./LoadingService";
@Injectable()
export class SharedDataService {
platform: string; //平臺
savePath: string; //儲存路徑
packageName: string; //包名
appVersion: string = '1.0.18'; //版本號
//。。。寫其他需要全域性呼叫的變數。。。
constructor() {}
}
注:程式碼中用的外掛是cordova-plugin-file-transfer,打包完成後會發現在android7版本上沒有問題,但是到android7以上的版本就有問題,可以下載到本地,但是沒有辦法在更新下載完成時,讓自動安裝,這個問題的解決辦法如下:
首先,新增完平臺:cordova platform add android時,開啟platform資料夾找到AndroidManifest.xml檔案,如下圖:
修改為:
<uses-sdk android:minSdkVersion="16" android:targetSdkVersion="23" />
再進行打包即可。