原生安卓集成Ionic3+CodePush

很多项目可能是在中途才从纯原生转向Hybrid,那就涉及到将Ionic、React Native等开发的功能模块集成到已有的原生安卓项目中,那么非原生的部分当然就需要热更新了,否则每次都打包apk就失去这么做的意义了。
本人也是在网上查看了一些文章,看了一些相关书本,把项目集成好了决定整理一下写下本文,供大家参考,有不对的地方欢迎指出。

环境:

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的环境咱就跳过吧(0_0)

参考:

Ionic创建项目以及集成code-push官方文档: https://ionicframework.com/docs/native/code-push/
Ionic集成到原生安卓项目:https://blog.csdn.net/qq_42618969/article/details/81173034

创建项目:

首先打开命令行,进入指定路径(项目路径根据个人情况自行修改),一波连续操作:

ionic start codepush-ionic-test tabs

创建tabs基础ionic项目(这里我并没有选择使用Ionic4,Ionic的资料有点少,所以不想用beta版本给自己找坑)


创建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中创建项目(苹果端替换android为ios)

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

如果已经创建了项目忘记了项目的key可以通过这个命令查看

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

在项目根目录打开config.xml,将code-push的key添加进去


    


    

编辑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);
      
     }
   );
  }

}

接下来在电脑浏览器运行一下,继续命令行

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  in config.xml
        loadUrl(getIntent().getStringExtra("url"));
    }
}

这时已经可以运行原生安卓项目了。当然,还有热更新没测试,再回到Ionic项目中,打开源码src文件夹随便修改点东西,然后命令行编译一下

ionic cordova prepare android

这时候再上传推送包到微软的code-push中,命令中的0.0.1是版本号,用原生安卓项目的versionName的值,--description后面跟的是热更新包的说明,-d后面跟的是推送分支,code-push创建项目后便会生成正式线和测试线两个分支,

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也可以动态修改,在代码里控制测试线、正式线以及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包运行时,发现code-push不检测更新,在代码里找了好几圈,看Android Studio中的Logcat发现日志出现了检测更新的请求,说网络连接有问题,才明白code-push对网络有做检查,release包运行一旦有网络代理就不会发起请求,这是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其它代码。

发包对应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的版本

完结,感谢阅读~

你可能感兴趣的:(原生安卓集成Ionic3+CodePush)