GMU小程序SDK集成(Android)

一、概述

GMU小程序SDK为使用者提供了一套完整的小程序方案,它包含GMU小程序页面渲染、页面堆栈管理、小程序版本发布、用户反馈的功能。

二、集成前准备

1、平台配置

  • 小程序SDK与服务端通信时的鉴权流程依赖GMU小程序开放平台提供的“应用KEY”和“应用SECRET”,因此SDK初始化时需要提供“应用KEY”和“应用SECRET”。

  • 除了“应用KEY”和“应用SECRET”,android还需额外配置apk签名串,如图所示:

获取方式如下:

使用 keytool(需安装java jdk)找到keystore文件,获取SHA1值

1)Ctrl+R快捷键,调出窗口,输入cmd进入控制台。

2)控制台进入到jdk下的bin目录,例:cd C:\Program Files\Java\jdk1.8.0_131\bin回车键;
再输入keytool -list -keystore keystore文件的路径,例:keytool -list -keystore C:\Users\Administrator\Desktop\xxx.keystore,回车键执行读取签名文件
提示输入密钥库口令,输入密钥后回车(如果没设置密码,可直接回车)此时可在控制台显示的信息中获取SHA1值,例如:39:CC:E7:7D:01:6C:0A:1A:CA:3D:13:20:D7:2D:C0:50:4B:38:4C:21,将SHA1值的冒号去除,大写字母改为小写后填入平台,例如:39cce77d016c0a1aca3d1320d72dc0504b384c21

2、集成清单

SDK库文件

  • miniappsdk.aar,登录您的GMU小程序开放平台账号,从左侧SDK集成页面上下载。

系统库依赖

  • SDK 28
  • build tool 28.0.3
  • support-v4:28.0.0
  • appcompat-v7:28.0.0
  • preference-v7:28.0.0

三方库依赖

  • Gson
  • OKHttp 3
  • Glide 4.9
  • J2V8

三、集成说明

1、编译必要配置

build.gradle配置

1.配置框架必要项

2.指定库路径,这里举例将库路径指定为工程根路径的libs文件夹下(这个路径开发者自行分配这里只是举例,gradle依赖列表中的所所有配置以此为根据编写)

3.依赖库

android{
...
defaultConfig {
resValue "string", "lightAppid",""
applicationId "apk包名"
android.defaultConfig.manifestPlaceholders.label = "应用名称,这个文案将影响到已运行的小程序在最近列表页中显示的标题"
ndk {
abiFilters "armeabi-v7a","armeabi"
}
}

repositories {
flatDir {
dirs '../libs'
}
}
...
}

dependencies {
implementation 'com.android.support:support-v4:28.0.0'
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support:preference-v7:28.0.0'
implementation 'com.squareup.okio:okio:1.15.0'
implementation 'com.squareup.okhttp3:okhttp:3.12.0'
implementation 'commons-net:commons-net:3.3'
implementation 'com.google.code.gson:gson:2.8.0'
//框架图片库依赖,glide 4.9
implementation('com.github.bumptech.glide:glide:4.9.0', {
exclude group: "com.android.support"
})
//框架小程序依赖
implementation(name:'j2v8-6.0.0',ext:'aar',group:'com.eclipsesource.j2v8',version:'1.0')
implementation(name:'miniappsdk-0.1',ext:'aar')
}

2、运行必要配置

AndroidManifest.xml配置

为适配Android11存储方面的修改,框架需要使用FileProvider加载文件。如果您的工程里已经包含了包名.provider这样的配置,则只需要在android:resource中指定的路径配置文件里添加我们框架需要的配置即可。

<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/>
</provider>

关联到资源文件res/xml/provider_paths.xml

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<paths>
<external-path
name="download"
path="."/>
<external-path
name="external_storage_root"
path="." />
<files-path
name="files-path"
path="." />
<cache-path
name="cache-path"
path="." />
<!--/storage/emulated/0/Android/data/...-->
<external-files-path
name="external_file_path"
path="." />
<!--代表app 外部存储区域根目录下的文件 Context.getExternalCacheDir目录下的目录-->
<external-cache-path
name="external_cache_path"
path="." />
<!--配置root-path。读取到sd卡和一些应用分身的目录,否则可能会导致 java.lang.IllegalArgumentException: Failed to find configured root that ...-->
<root-path
name="root-path"
path="" />
</paths>
</paths>

该资源文件放置在下图所示的路径:

四、权限声明

框架所有必要权限都已经在包内声明,外部不用再在AndroidManifest.xml文件中声明。框架提供了现式的获取危险权限的的API PermissionsHelper,用法在框架启动示例代码中已经展示。

五、API设计

1、框架初始化

GMUMiniApi init 必须定义在Applicaiton中,否则小程序无法正常运行
| 入参类型及范围 | 说明 |
| :—-| :—- |
|Context|不可为空|

public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
String processName = getProcessName();
//判断不等于默认进程名称,AndroidP上子进程若要访问网络必须做此操作
if (!getPackageName().equals(processName)){
WebView.setDataDirectorySuffix(processName);
}
}
//必:初始化GMU框架
GMUMiniApi.getInstance().init(this);
}
}

2、框架启动

GMUMiniApi startWithConfig 框架启动方法
| 入参类型及范围 | 说明 |
| :—-| :—- |
|config|必传。SDK初始化配置对象,配置对象需要提供必需的appKeyappSecret。如果SDK需要连接1.0私有云平台,可为配置对象提供server属性来指定私有云服务器;|
|GMUMiniApi.StartStatus|可为空。若预置了小程序的资源包数量比较多的话,初始化会比较耗时,若不监听则会在后台做资源准备工作,需要确保在用户打开小程序前是执行完毕的|

//想要框架所有功能能够正常使用,建议在初始化时请求READ_PHONE_STATE、WRITE_EXTERNAL_STORAGE这两个必要权限。
String[] permissions = {Manifest.permission.READ_PHONE_STATE,Manifest.permission.WRITE_EXTERNAL_STORAGE};
PermissionsHelper.checkPermission(this,permissions, new PermissionCallBack() {
@Override
public void onSucessed(Bundle bundle) {
GMUMiniConfig config = new GMUMiniConfig();
config.server = "https://mpapi.lightyy.com";
config.appKey = "b489e314f4e247339d41cbb34ea0000";
config.appSecret = "b71b317768274cf7ae22b90478200000";
//这里是真正启动框架的代码
GMUMiniApi.getInstance().startWithConfig(config,new GMUMiniApi.StartStatus() {
@Override
public void onStart(boolean b) {
//b为true表示启动成功,false表示失败
}
});
}

@Override
public void onFailed(Bundle bundle) {

}
});

GMUMiniApi start(已废弃) 框架启动方法
| 入参类型及范围 | 说明 |
| :—-| :—- |
|GMUMiniApi.StartStatus|可为空。若预置了小程序的资源包数量比较多的话,初始化会比较耗时,若不监听则会在后台做资源准备工作,需要确保在用户打开小程序前是执行完毕的|

//想要框架所有功能能够正常使用,建议在初始化时请求READ_PHONE_STATE、WRITE_EXTERNAL_STORAGE这两个必要权限。
String[] permissions = {Manifest.permission.READ_PHONE_STATE,Manifest.permission.WRITE_EXTERNAL_STORAGE};
PermissionsHelper.checkPermission(this,permissions, new PermissionCallBack() {
@Override
public void onSucessed(Bundle bundle) {
//这里是真正启动框架的代码
GMUMiniApi.getInstance().start(new GMUMiniApi.StartStatus() {
@Override
public void onStart(boolean b) {
//b为true表示启动成功,false表示失败
}
});
}

@Override
public void onFailed(Bundle bundle) {

}
});

3、打开小程序

GMUMiniApi openMiniApp 打开平台上发布的小程序
| 入参类型及范围 | 说明 |
| :—-| :—- |
|Context|不可为空|
|String|平台上发布的小程序的id|

GMUMiniApi.getInstance().openMiniApp(context,"GMUMINIAPPSDK");

六、混淆配置

框架提供的公共类和接口都不应该被混淆,若您的APK需要混淆请加上这些配置:

--dontoptimize
-dontusemixedcaseclassnames
-dontpreverify
-verbose
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
-keepattributes Signature
-keepattributes *Annotation*
-dontskipnonpubliclibraryclassmembers #保留所有public类和方法
#常规避免混淆方法,避免混淆自定义的页面,服务,广播,自定义的页面组件,枚举,序列化包
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider

-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet);
}

-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet, int);
}

-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}

-keep class * implements android.os.Parcelable {
public *;
}

-keep public class * {
public *;
}

-keep public class com.hundsun.miniapp.LMAFragment{
protected *;
}

-keep public interface com.hundsun.miniapp.debug.IDebugManager{
*;
}

-keep public interface com.hundsun.miniapp.ILMAJSBridge{
*;
}

-keep public class com.hundsun.miniapp.LMAInfo{
public *;
}

-keep public class com.hundsun.miniapp.LMAInfo$*{
<fields>;
<methods>;
}

-keepclassmembernames class com.hundsun.miniapp.LMAInfo{*;}
-keepclassmembernames class com.hundsun.miniapp.LMAContext{*;}

-keep public class com.hundsun.miniapp.LMAJSObject{
public *;
protected *;
*** onNativeCalled(...);
*** onNativeDisposed(...);
}

-keep public class com.hundsun.miniapp.LMAJSCoreBridge{
*** createAsyncExecutor(...);
*** executeScript(...);
*** disposeAsyncExecutor(...);
*** getGlobalObjectRef(...);
*** getObjectPropertyRef(...);
*** addObjectProperty(...);
*** addObjectFunction(...);
*** protectObjectRef(...);
*** unprotectObjectRef(...);
*** deletePurgedContextObjectRef(...);
*** callObjectRefFunction(...);
*** tickTimer(...);
}

#不混淆三方库
-keep class com.eclipsesource.** {*;}