原生安卓集成Ionic3+CodePush

很多項目可能是在中途才從純原生轉向Hybrid蕴纳,那就涉及到將Ionic导帝、React Native等開發(fā)的功能模塊集成到已有的原生安卓項目中堡称,那么非原生的部分當然就需要熱更新了,否則每次都打包apk就失去這么做的意義了墙贱。
本人也是在網上查看了一些文章热芹,看了一些相關書本,把項目集成好了決定整理一下寫下本文惨撇,供大家參考伊脓,有不對的地方歡迎指出。

環(huán)境:

Android Studio 3.2 + JDK 1.8 + node.js 10.13.0 + ionic 4.3.1 + cordova 8.1.2 + code-push 2.1.9

npm命令搭建Ionic的環(huán)境咱就跳過吧(0_0)

參考:

Ionic創(chuàng)建項目以及集成code-push官方文檔: https://ionicframework.com/docs/native/code-push/
Ionic集成到原生安卓項目:https://blog.csdn.net/qq_42618969/article/details/81173034

創(chuàng)建項目:

首先打開命令行魁衙,進入指定路徑(項目路徑根據個人情況自行修改)报腔,一波連續(xù)操作:

ionic start codepush-ionic-test tabs

創(chuàng)建tabs基礎ionic項目(這里我并沒有選擇使用Ionic4,Ionic的資料有點少剖淀,所以不想用beta版本給自己找坑)


創(chuàng)建tabs樣式的ionic3項目
不需要Ionic Pro SDK
cd codepush-ionic-test

進入項目文件夾

ionic cordova plugin add cordova-plugin-code-push

添加code-push插件


添加cordova可能會比較慢纯蛾,感覺卡住的話Ctrl + C然后重新添加code-push
npm install --save @ionic-native/code-push

node_modules添加code-push庫


添加code-push
ionic cordova platform add android

Ionic添加安卓平臺支持(不添加的話項目只是web,蘋果平臺將android改為ios即可)

npm install

安裝code-push-cli(這個一定加上-g表明全局安裝纵隔,以后就可以省略這步)

npm install -g code-push-cli

登錄code-push(這一步會自動打開電腦瀏覽器翻诉,注冊賬號或者使用github賬號登錄都行炮姨,登錄后會給一個token)

code-push login
code-push賬號token

將code-push賬號token黏貼到命令行

在code-push中創(chuàng)建項目(蘋果端替換android為ios)

code-push app add codepush-ionic-test-android android cordova
項目key

如果已經創(chuàng)建了項目忘記了項目的key可以通過這個命令查看

code-push deployment ls codepush-ionic-test-android -k

在項目根目錄打開config.xml,將code-push的key添加進去

<platform name="android">
    <preference name="CodePushDeploymentKey" value="*******" />
</platform>
<platform name="ios">
    <preference name="CodePushDeploymentKey" value="*******" />
</platform>

編輯src/app/app.module.ts代碼如下(這個有點像安卓中的build.gradle碰煌,這里主要是設置CodePush庫引用):

import { NgModule, ErrorHandler } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { IonicApp, IonicModule, IonicErrorHandler } from 'ionic-angular';
import { MyApp } from './app.component';

import { AboutPage } from '../pages/about/about';
import { ContactPage } from '../pages/contact/contact';
import { HomePage } from '../pages/home/home';
import { TabsPage } from '../pages/tabs/tabs';

import { StatusBar } from '@ionic-native/status-bar';
import { SplashScreen } from '@ionic-native/splash-screen';
import { CodePush } from '@ionic-native/code-push';

@NgModule({
  declarations: [
    MyApp,
    AboutPage,
    ContactPage,
    HomePage,
    TabsPage
  ],
  imports: [
    BrowserModule,
    IonicModule.forRoot(MyApp)
  ],
  bootstrap: [IonicApp],
  entryComponents: [
    MyApp,
    AboutPage,
    ContactPage,
    HomePage,
    TabsPage
  ],
  providers: [
    StatusBar,
    SplashScreen,
    CodePush,
    {provide: ErrorHandler, useClass: IonicErrorHandler}
  ]
})
export class AppModule {}

編輯src/app.component.ts添加熱更新的檢查更新方法(這個有點類似application初始化):

import { Component } from '@angular/core';
import { Platform } from 'ionic-angular';
import { StatusBar } from '@ionic-native/status-bar';
import { SplashScreen } from '@ionic-native/splash-screen';

import { HomePage } from '../pages/home/home';

import { CodePush, InstallMode, SyncStatus } from '@ionic-native/code-push';
import { AlertController } from 'ionic-angular/components/alert/alert-controller';

@Component({
  templateUrl: 'app.html'
})
export class MyApp {
  rootPage:any = HomePage;

  constructor(platform: Platform, statusBar: StatusBar, splashScreen: SplashScreen,
              private codePush: CodePush,  private alertCtrl: AlertController) {
    platform.ready().then(() => {
      // Okay, so the platform is ready and our plugins are available.
      // Here you can do any higher level native things you might need.
      statusBar.styleDefault();
      splashScreen.hide();
      this.checkCodePush(); //Use the plugin always after platform.ready()
    });
  }

  checkCodePush() {
    
     this.codePush.sync({
      updateDialog: {
       appendReleaseDescription: true,
       descriptionPrefix: "\n\nChange log:\n"   
      },
      installMode: InstallMode.IMMEDIATE
   }).subscribe(
     (data) => {
      console.log('CODE PUSH SUCCESSFUL: ' + data);
      
     },
     (err) => {
      console.log('CODE PUSH ERROR: ' + err);
      
     }
   );
  }

}

接下來在電腦瀏覽器運行一下舒岸,繼續(xù)命令行

ionic serve
在web端顯示效果

到這里就已經將Ionic集成code-push了,最后編譯安卓項目

ionic cordova build android

集成到原生安卓項目

Ionic項目中找到安卓項目芦圾,就在platforms文件夾里面(ios項目路徑也在這)吁津,這已經是一個能直接用Android Studio打開的項目了。
1堕扶、將其中的CordovaLib整個文件夾拷貝到要集成的原生安卓項目中碍脏,在gradle配置一下作為module。
2稍算、將項目中res/xml/config.xml文件拷貝到原生項目中典尾,將Ionic項目中的“org文件夾、io文件夾”拷貝到原生項目的main/java下糊探。
3钾埂、接下來是將Ionic中寫的功能相關代碼拷貝到原生項目中,也就是assets中的www文件夾科平,里面才是在Ionic中的代碼褥紫,而熱更新便是更新這里面的內容。

其實如果是集成Ionic到原生項目的話瞪慧,到這里已經完成了髓考,但是code-push還沒放進去。

4弃酌、在安卓原生項目中添加依賴(這個庫在Ionic安卓項目的cordova-plugin-code-push/starter-build-extras.gradle中添加了引用)

implementation 'com.nimbusds:nimbus-jose-jwt:5.1'

5氨菇、拷貝Ionic安卓項目中的src/main/java/com到原生安卓項目中,最后原生項目文件結構如圖所示(馬賽克是原生項目本來的代碼):

項目結構

到這里整個項目集成Ionic + code-push就基本完成了妓湘,隨便找個地方從原生項目跳轉進Ionic的功能模塊里面(跳轉activity就好查蓉,跳到io.ionic.starter.MainActivity,記得到AndroidManifest.xml中添加這個Activity榜贴,這里為了省事我把Ionic的路徑直接一起傳過去)

Bundle bundle = new Bundle();
bundle.putString("url", "file:///android_asset/www/index.html");
IntentUtils.startActivity(mActivity, MainActivity.class, bundle);

再稍微改一下io.ionic.starter.MainActivity

public class MainActivity extends CordovaActivity
{
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);

        // enable Cordova apps to be started in the background
        Bundle extras = getIntent().getExtras();
        if (extras != null && extras.getBoolean("cdvStartInBackground", false)) {
            moveTaskToBack(true);
        }

        // Set by <content src="index.html" /> in config.xml
        loadUrl(getIntent().getStringExtra("url"));
    }
}

這時已經可以運行原生安卓項目了豌研。當然,還有熱更新沒測試唬党,再回到Ionic項目中鹃共,打開源碼src文件夾隨便修改點東西,然后命令行編譯一下

ionic cordova prepare android

這時候再上傳推送包到微軟的code-push中初嘹,命令中的0.0.1是版本號及汉,用原生安卓項目的versionName的值,--description后面跟的是熱更新包的說明屯烦,-d后面跟的是推送分支坷随,code-push創(chuàng)建項目后便會生成正式線和測試線兩個分支房铭,

code-push release codepush-ionic-test-android ./platforms/android/app/src/main/assets/www/ 0.0.1 --description "Your awesome change description" -d "Staging"
檢查更新

題外:

1、熱更新檢查可以不彈框提示采取靜默安裝温眉,具體的就自行去修改Ionic那部分代碼了缸匪,畢竟ios審核禁止熱更新,還是不能光明正大的类溢。配置在config.xml里面熱更新使用的key也可以動態(tài)修改凌蔬,在代碼里控制測試線、正式線以及ios和android闯冷,自己去做判斷就好砂心,簡單上幾行代碼:

//根據平臺修改key
if (this.platform.is('android')) {
    key = '';
} else if (this.platform.is('ios')) {
    key = '';
}
//定義檢查更新參數
let options = {
    installMode:InstallMode.ON_NEXT_RESUME,
    deploymentKey:key
}
//檢查更新方法
checkCodePush() {
  this.codePush.sync(options,(data) => {
    
 }).subscribe(
   (data) => {
    console.log('CODE PUSH SUCCESSFUL: ' + data);
    
   },
   (err) => {
    console.log('CODE PUSH ERROR: ' + err);
    
   }
 );
}

2、檢查更新有幾個模式蛇耀,這里用的是啟動Ionic的時候檢查更新辩诞,其它的自己加代碼吧,類似這樣:

//從后臺回到應用時檢查更新
this.platform.resume.subscribe(() => {
    this.checkCodePush();
});

3纺涤、另外說一下本人在集成過程中踩的一個坑译暂,因為用fiddler抓包,手機設置了代理撩炊,將集成好的安卓項目打包release包運行時外永,發(fā)現code-push不檢測更新,在代碼里找了好幾圈拧咳,看Android Studio中的Logcat發(fā)現日志出現了檢測更新的請求册着,說網絡連接有問題壤短,才明白code-push對網絡有做檢查台汇,release包運行一旦有網絡代理就不會發(fā)起請求即纲,這是https加密傳輸的SSL證書問題,具體的就不深究了谭网。
4、這里使用的是微軟code-push的服務赃春,也可以自行搭建一個code-push服務端愉择。
5、當然了织中,可以把www文件夾以及cdvasset.manifest文件放到自定義路徑:
一是使用自己的方式更新文件锥涕,只需要修改跳轉io.ionic.starter.MainActivity時傳過去的頁面路徑即可修改ionic頁面訪問。

//正常情況下讀取文件我們會這樣寫路徑
String path = Environment.getExternalStorageDirectory().getAbsolutePath() + "www/index.html"
//在這里需要加個前綴狭吼,像原本assets路徑類似
String path = "file:" + Environment.getExternalStorageDirectory().getAbsolutePath() + "www/index.html"

還有就是把codepush熱更新的路徑也改掉层坠,需要修改三個地方:

// com.microsoft.cordova.CodePush中的WWW_ASSET_PATH_PREFIX常量
private static final String WWW_ASSET_PATH_PREFIX = "file:" + Environment.getExternalStorageDirectory().getAbsolutePath() + "/www/";


// org.apache.cordova.ConfigXmlParser中的setStartUrl方法,這里是設置開始頁面
launchUrl = "file:" + Environment.getExternalStorageDirectory().getAbsolutePath()+"/www/index.html";


// org.apache.cordova.file.AssetFilesystem中的lazyInitCaches方法刁笙,注意這里無須添加“file:”破花,將原本打開assets路徑文件改為普通的打開文件并轉換成InputStream對象(FileInputStream是InputStream的子類)
ois = new ObjectInputStream(new FileInputStream(Environment.getExternalStorageDirectory().getAbsolutePath()+"/cdvasset.manifest"));

最后說一下谦趣,code-push一旦進行過熱更新后,文件會保存到內部存儲中座每,真正自定義還需要修改CodePush以及Cordova其它代碼前鹅。

發(fā)包對應APP版本范圍表達式

1.2.3——僅僅只有1.2.3的版本
*——所有版本
1.2.x——主要版本1,次要版本2的任何修補程序版本
1.2.3 - 1.2.7——1.2.3版本到1.2.7版本
>=1.2.3 <1.2.7——大于等于1.2.3版本小于1.2.7的版本
~1.2.3——大于等于1.2.3版本小于1.3.0的版本
^1.2.3——大于等于1.2.3版本小于2.0.0的版本

完結峭梳,感謝閱讀~

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末舰绘,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子葱椭,更是在濱河造成了極大的恐慌捂寿,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,602評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件孵运,死亡現場離奇詭異者蠕,居然都是意外死亡,警方通過查閱死者的電腦和手機掐松,發(fā)現死者居然都...
    沈念sama閱讀 88,442評論 2 382
  • 文/潘曉璐 我一進店門踱侣,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人大磺,你說我怎么就攤上這事抡句。” “怎么了杠愧?”我有些...
    開封第一講書人閱讀 152,878評論 0 344
  • 文/不壞的土叔 我叫張陵待榔,是天一觀的道長。 經常有香客問我流济,道長锐锣,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,306評論 1 279
  • 正文 為了忘掉前任绳瘟,我火速辦了婚禮雕憔,結果婚禮上,老公的妹妹穿的比我還像新娘糖声。我一直安慰自己斤彼,他們只是感情好,可當我...
    茶點故事閱讀 64,330評論 5 373
  • 文/花漫 我一把揭開白布蘸泻。 她就那樣靜靜地躺著琉苇,像睡著了一般。 火紅的嫁衣襯著肌膚如雪悦施。 梳的紋絲不亂的頭發(fā)上并扇,一...
    開封第一講書人閱讀 49,071評論 1 285
  • 那天,我揣著相機與錄音抡诞,去河邊找鬼穷蛹。 笑死土陪,一個胖子當著我的面吹牛,可吹牛的內容都是我干的俩莽。 我是一名探鬼主播旺坠,決...
    沈念sama閱讀 38,382評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼扮超!你這毒婦竟也來了取刃?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,006評論 0 259
  • 序言:老撾萬榮一對情侶失蹤出刷,失蹤者是張志新(化名)和其女友劉穎璧疗,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體馁龟,經...
    沈念sama閱讀 43,512評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡崩侠,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,965評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了坷檩。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片却音。...
    茶點故事閱讀 38,094評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖矢炼,靈堂內的尸體忽然破棺而出系瓢,到底是詐尸還是另有隱情,我是刑警寧澤句灌,帶...
    沈念sama閱讀 33,732評論 4 323
  • 正文 年R本政府宣布夷陋,位于F島的核電站,受9級特大地震影響胰锌,放射性物質發(fā)生泄漏骗绕。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,283評論 3 307
  • 文/蒙蒙 一资昧、第九天 我趴在偏房一處隱蔽的房頂上張望酬土。 院中可真熱鬧,春花似錦榛搔、人聲如沸诺凡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至嘶卧,卻和暖如春尔觉,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背芥吟。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評論 1 262
  • 我被黑心中介騙來泰國打工侦铜, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留专甩,地道東北人。 一個月前我還...
    沈念sama閱讀 45,536評論 2 354
  • 正文 我出身青樓钉稍,卻偏偏與公主長得像涤躲,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子贡未,可洞房花燭夜當晚...
    茶點故事閱讀 42,828評論 2 345