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
<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 {
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初始化配置对象,配置对象需要提供必需的appKey
和appSecret
。如果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() {
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() {
public void onStart(boolean b) {
//b为true表示启动成功,false表示失败
}
});
}
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() {
public void onSucessed(Bundle bundle) {
//这里是真正启动框架的代码
GMUMiniApi.getInstance().start(new GMUMiniApi.StartStatus() {
public void onStart(boolean b) {
//b为true表示启动成功,false表示失败
}
});
}
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.** {*;}