需要Hbuilder和Android Studio,前往官网下载即可
HBuilderX官网下载
Android Studio 官网下载
uni-app原生开发SDK最新版本下载
打开Hbuilder,左上角文件->新建->项目,选择项目类型为uni-app,选择合适的项目模板
打开Android Studio,左上角File->new->new Project,选择设备类型Phone and Tablet,选择初始有一个空的Activity,点击Next,设置应用名称,选择最小SDK,勾选下面的Use legacy…,Finish,项目创建完成
有两种目录结构比较常用,Project和Android,平时开发主要使用Android,但是文件显示的不够全面,我们这里拿Project来看一下所生成的Android原生项目的目录结构
如果gradle版本过高会出问题,所以检查下版本,查看以下两个文件,DCloud推荐gradle-4.6-all版本,tools.build版本为3.2.1
之后,我们还需要引入uni-app开发所需要的aar包以及添加依赖
我们已经下载了uni-app原生开发SDK(如果没有下载,可以回到文档最上方,点击链接下载),将我们需要的aar包放在app的libs中,并在build.gradle中添加依赖
代码块:
aaptOptions {
additionalParameters '--auto-add-overlay'
ignoreAssetsPattern "!.svn:!.git:.*:!CVS:!thumbs.db:!picasa.ini:!*.scc:*~"
}
//uni-app添加
implementation fileTree(include: ['*.aar'], dir: 'libs')
/*uniapp集成所需库-----------------------开始*/
implementation 'com.android.support:recyclerview-v7:26.1.0'
implementation 'com.alibaba:fastjson:1.1.46.android'
implementation 'com.facebook.fresco:fresco:1.13.0'
implementation "com.facebook.fresco:animated-gif:1.13.0"
/*uniapp集成所需库-----------------------结束*/
uni-app插件目前仅支持Module扩展和Component扩展
我们这里先学习Module扩展
左上角File,new->new Module,选择Android Library,点击Next,设置模块名称Module name,以及包名和最小SDK minimum SDK,注意与创建项目时选择一致,如果不小心选择错误也没事,可以在build.gradle中进行修改,之后Finish
我们已经在主项目中添加了aar,在Module中只需要在build.gradle中引入即可,其中uniapp-v8-release.aar是扩展module主要依赖库,必须导入此依赖库!
我们需要创建一个继承UNIModule的类,这里我们写与js交互的方法逻辑,需要注意以下两点:
扩展方法必须加上@UniJSMethod (uiThread = false or true) 注解。UniApp 会根据注解来判断当前方法是否要运行在 UI 线程,和当前方法是否是扩展方法。
UniApp是根据反射来进行调用 Module 扩展方法,所以Module中的扩展方法必须是 public 类型。同样因为是通过反射调用,Module 不能被混淆。请在混淆文件中添加代码:
-keep public class * extends io.dcloud.feature.uniapp.common.UniModule{*;}
我们在app模块下的src/main下创建assets文件夹,创建dcloud_uniplugins.json文件,注册我们创建的插件
dcloud_uniplugins.json说明
nativePlugins: 插件跟节点 可存放多个插件
hooksClass: 生命周期代理(实现AppHookProxy接口类)格式(完整包名加类名)
plugins: 插件数组
name : 注册名称
class : module 或 component 实体类完整名称
type : module 或 component类型。
我们需要修改我们创建的uni-app项目调用插件里的方法,那我们就简单写一个调用来进行测试。
我们简单写了一个按钮,调用原生方法,发送参数并返回数据,展示在textArea中
当我们写完代码,可以先运行测试一下代码是否有问题,防止多次修改多次编译
确定代码没有问题,就可以编译资源包,点击上方发行->原生APP-本地打包->生成本地打包APP资源,这里需要微信开发者工具,根据提示下载引入即可,编译完成,控制台会打印资源包路径
将资源包复制到src/main/assets/apps下,如果没有apps文件夹,则创建,之后从我们下载的原生开发SDK中复制data文件夹到assets下,修改dcloud_control.xml中appid与我们项目的appid一致
修改了这些还是不够,还需要修改app下AndroidManifest.xml,我们原先是有一个默认的Activity的,删掉,将下面的内容复制进去,然后修改provider标签的authorities,修改为自己的包名
<activity
android:name="io.dcloud.PandoraEntry"
android:configChanges="orientation|keyboardHidden|keyboard|navigation"
android:label="@string/app_name"
android:launchMode="singleTask"
android:hardwareAccelerated="true"
android:theme="@style/TranslucentTheme"
android:screenOrientation="user"
android:windowSoftInputMode="adjustResize" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
intent-filter>
activity>
<activity
android:name="io.dcloud.PandoraEntryActivity"
android:launchMode="singleTask"
android:configChanges="orientation|keyboardHidden|screenSize|mcc|mnc|fontScale|keyboard"
android:hardwareAccelerated="true"
android:permission="com.miui.securitycenter.permission.AppPermissionsEditor"
android:screenOrientation="user"
android:theme="@style/DCloudTheme"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<action android:name="android.intent.action.VIEW" />
<data android:scheme="h56131bcf" />
intent-filter>
activity>
<provider
android:name="io.dcloud.common.util.DCloud_FileProvider"
android:authorities="包名.dc.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/dcloud_file_provider" />
provider>
4) 插件模块修改
我们只修改VUE代码显然是不够的,还需要在java中实现对应的方法,否则会报错,我们在VUE中调用了getLocation方法,而且有参数和返回值,那么我们就在java中进行对应的实现
5)运行
点击Android Studio的run 或者 debug来运行APP,点击按钮测试,可以看到已经成功调用
其实上述的方法是以原生开发为主导,如果是以vue开发为主导,需要将我们的插件模块,封装为一个插件包,首先,我们打开gradle,选择插件模块,Tasks->other->assembleRelease,双击执行,生成aar文件
之后,在我们的uni-app项目根目录下,新建nativeplugins文件夹,新建我们的插件文件夹,然后新建android文件夹,将我们的aar文件复制进来,如果有第三方jar包或者so库可以放在libs文件夹,创建package.json,可以查看官网说明
HbuilderX,点击上方工具栏,选择发行->原生App-云打包,之后进行部分设置,主要需要注意的部分如下,点击打包即可,我们可以点击发行->原生App-查看云打包状态,查看云打包进度,如果打包完成,在控制台会打印下载链接,下载APK即可
安装后进行测试,功能正常
可以参考官方文档 Android平台App本地离线打包
其实最开始,我们是直接运行在真机,但是会出现如下报错TypeError undefined
这是由于原生插件需要先进行云打包更新基座,所以我们进行了云打包,报错消失,调用插件正常
现在我们尝试第二种方式,本地离线打包
创建一个包含空Activity的项目。
与之前类似,就不再多说,参考 二-2 创建原生项目。
注意:App离线SDK不支持Kotlin
拿到我们的插件生成的aar,放到libs文件夹
将lib.5plus.base-release.aar、[email protected]、uniapp-release.aar和miit_mdid_1.0.10.aar(HBuilderX2.8.1之后更新到msa_mdid_1.0.13.aar)拷贝到libs目录下
注意:自HBuilderX2.8.0开始,JS引擎默认从jscore改为V8,提升运算性能,离线sdk自HBuilderX2.8.1也将默认JS引擎切换到V8,新增uniapp-v8-release.aar(uniapp-v8-release.aar和uniapp-release.aar不能同时使用。)。
在build.gradle中添加资源引用
implementation fileTree(dir: 'libs', include: ['*.aar', '*.jar'], exclude: [])
implementation "com.android.support:support-v4:28.0.0"
implementation "com.android.support:appcompat-v7:28.0.0"
implementation 'com.android.support:recyclerview-v7:28.0.0'
implementation 'com.facebook.fresco:fresco:1.13.0'
implementation "com.facebook.fresco:animated-gif:1.13.0"
implementation 'com.github.bumptech.glide:glide:4.9.0'
implementation 'com.alibaba:fastjson:1.1.46.android'
uni-app配置时需要在build.gradle中添加aaptOptions配置
aaptOptions {
additionalParameters '--auto-add-overlay'
ignoreAssetsPattern "!.svn:!.git:.*:!CVS:!thumbs.db:!picasa.ini:!*.scc:*~"
}
注意:更新SDK时需要同时更新aar/jar文件和build.gradle配置
配置应用启动页及provider节点,删除AndroidManifest.xml中初始的Activity标签,将下述内容添加到Androidmanifest.xml的application节点中
注意:${apk.applicationId} 必须替换成当前应用的包名
<activity
android:name="io.dcloud.PandoraEntry"
android:configChanges="orientation|keyboardHidden|keyboard|navigation"
android:label="@string/app_name"
android:launchMode="singleTask"
android:hardwareAccelerated="true"
android:theme="@style/TranslucentTheme"
android:screenOrientation="user"
android:windowSoftInputMode="adjustResize" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
intent-filter>
activity>
<activity
android:name="io.dcloud.PandoraEntryActivity"
android:launchMode="singleTask"
android:configChanges="orientation|keyboardHidden|screenSize|mcc|mnc|fontScale|keyboard"
android:hardwareAccelerated="true"
android:permission="com.miui.securitycenter.permission.AppPermissionsEditor"
android:screenOrientation="user"
android:theme="@style/DCloudTheme"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<action android:name="android.intent.action.VIEW" />
<data android:scheme="h56131bcf" />
intent-filter>
activity>
<provider
android:name="io.dcloud.common.util.DCloud_FileProvider"
android:authorities="${apk.applicationId}.dc.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/dcloud_file_provider" />
provider>
!!!注意:gradle版本不可过高,注意和com.android.tools.build:gradle同步修改
插件包都有package.json文件,放在原生项目中就可以将里面的内容复制到assets下的dcloud_uniplugins.json中,前面也提到过这个文件 二-4-1)注册插件
Android studio默认项目没有assets文件夹,需手动创建,创建位置与java目录同级,创建data文件夹并将SDK->assets->data文件夹拷贝到刚刚创建的assets文件夹下,将uni-app打成资源包放在assets/apps下,修改dcloud_control.xml中的appid为拷贝过来的APP的id,之前已经有说明,就不再配图
生成自定义基座,需要在根节点下添加debug="true"和syncDebug=“true”,如下图:
运行测试成功。
注意修改AndroidManifest.xml,删除默认的Activity,复制我们需要的内容进去
看是不是gradle版本过高,DCloud推荐gradle-4.6-all版本,tools.build版本为3.2.1
可以搞一个透明Activity申请权限,申请成功后,调用finish()关闭activity
可以在AndroidManifest.xml中设置activity的android:theme="@android:style/Theme.Translucent"使Activity透明
是由于我们所使用的so库与手机架构不匹配,可以在app下的build.gradle文件中的android标签下的defaultConfig标签中添加如下代码
ndk {
//设置支持的SO库架构(开发者可以根据需要,选择一个或多个平台的so)
abiFilters “armeabi-v7a”
}
百度有人说是由于aar打包的时候jar包里的assets没有打进去
没有找到合适的解决方案,只能把jar包和so库提出来放在插件包里,修改插件模块下build.gradle,这样打包成aar的时候就不会把jar和so也打进去,然后在调用插件的项目中引入这些jar和so
注意这个超限不是说打包后的安装包过大,而是资源包以及本地插件等的大小,这是由于我们把第三方framework也放在了插件文件夹中,例如我们项目使用的高德导航SDK,有五百多M。
这种情况有两种解决方案:
① 将插件发布至插件市场,以云端插件的方式引入插件,进行云打包
这种方式的弊端就是别人也可以使用你的插件,如果设置了插件价格,即便是插件作者使用插件也需要收费,当然收益还是给到插件作者,也就是付给DCloud一个分成费。
② 如果没有使用插件市场的其他插件,可以使用XCode本地打包