English
This article aims to help Android developers get started with UTS quickly.
Readers are required to have Android native application development experience.
UTS插件
是uni-app
新型插件形式,拥有跨平台,高效率,易调试等优点。详情
For Android developers, what we need to know is:
UTS
source code file, the IDE will synchronously compile it into the corresponding Kotlin code.因为UTS语法与kotlin很类似,建议快速阅读后,在实践中掌握这UTS语法。uts语法介绍。
Compared with js, the syntax of uts is more similar to java. However, there are still big differences, and you need to read the 2.3 grammar section in detail.
Although the development of UTS plug-ins does not require mastering kotlin, since UTS
is currently on the android platform, it will be compiled into kotlin source code. Learn the kotlin language to facilitate troubleshooting and implementation of complex functions.
Therefore, it is recommended to learn kotlin syntax.
kotlin https://kotlinlang.org/
kotlin for android https://developer.android.com/kotlin
Although UTS and koltin are basically consistent in data types, there are still differences in some scenarios, which are specifically explained here
In principle:
**The data type is subject to the built-in type of UTS, and each native platform will automatically adapt to it. **
**But UTS itself is a cross-platform language. When the API of a specific platform has clear requirements, the data type clearly required by the other party shall prevail. **
By default UTS
developers can use Number
to override the scenario of using Int
on the android
platform.
But when the developer rewrites the onStartCommand
method of the Service
component, the Android
API requires that the last two parameters must be Int
In the native development environment, it should be written like this:
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
return super.onStartCommand(intent, flags, startId);
}
In the standard TS environment, there is only Number
type and no Int
type
In order to adapt to this situation, UTS allows developers to use the data type Int of the native platform to meet the data type requirements of the native API:
override onStartCommand(intent:Intent ,flags:Int ,startId:Int):Int {
return super.onStartCommand(intent, flags, startId);
}
MutableList
MutableList
is a unique data type of the android
platform. In general scenarios, the built-in type Array
in UTS can be used instead
However, when calling the onAppActivityRequestPermissionsResult
function to monitor the result of the permission application, it is explicitly required to use this type of parameter
In the native environment, it should be written like this:
onAppActivityRequestPermissionsResult(fun(requestCode: Number, permissions: MutableList<String>, grantResults: MutableList<Number>){
});
In the standard TS environment, there is no MutableList
type, and the similar data type is Array
In order to adapt to this situation, UTS allows developers to use the data type MutableList
of the native platform to meet the data type requirements of the native platform API:
onAppActivityRequestPermissionsResult((requestCode: number,permissions: MutableList<string>,grantResults: MutableList<number>) => {
});
String[]
部分三方sdk 使用java开发,要求继承/实现的方法参数为 string[]类型,这种情况比较特殊,需要将kotlin.Array先进行别名声明,再继续使用
import KotlinArray from 'kotlin.Array';
class XXX{
override onCaptureFinish(p0: KotlinArray<string>){
// do sth
};
}
In the UTS environment, there is no thread concept by default. The code is executed in a separate thread pool of uts by default.
If you need to perform asynchronous tasks, it is recommended to execute them through the built-in function setTimeOut
console.log("这里是UTS默认线程 :" + Thread.currentThread().getName())
setTimeOut(function(){
console.log("这里是异步任务线程 :" + Thread.currentThread().getName())
},1000)
If it is an android native api that requires some code to be executed on the UI thread, it needs to be operated through the native api:
class AddUIRunnable extends Runnable {
override run():void {
// do something
console.log("这里是android平台主线程 :" + Thread.currentThread().getName())
}
};
let uiRunable = new AddUIRunnable();
getUniActivity()!.runOnUiThread(uiRunable)
For Android projects, in addition to source code, it also involves common issues such as dependencies, resources, and configurations.
This chapter will introduce how to configure these properties in the UTS plug-in development environment
注意:
Take the configuration file in the native-page plug-in in hello UTS as an example:
Example file location in hello uts:
~\uni_modules\uts-nativepage\utssdk\app-android\AndroidManifest.xml
AndroidManifest.xml example:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"
// 注意:这里是插件的包名而不是应用的包名
package="io.dcloud.uni_modules.utsNativepage">
// configure permissions
<!--Create foreground service permissions-->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<application>
// configure service / activity
<service android:name="uts.sdk.modules.utsNativepage.ForeService" />
<activity android:name="uts.sdk.modules.utsNativepage.DemoActivity"></activity>
</application>
</manifest>
AndroidManifest.xml configuration rules are consistent with those in android.
Special Note:
Each UTS plugin corresponds to a lib module in the android project.
Unlike you manually enter the package name in android studio, if you do not have a manual package name, HX will generate one by default according to the following rules:
uts插件默认包名规则:
如果是根目录utssdk下的uts插件
包名:uts.sdk.(插件ID转驼峰)
如果是uni_modules目录下的uts插件
包名:uts.sdk.modules.(插件ID转驼峰)
举例:
uni-getbatteryinfo -> uts.sdk.modules.uniGetbatteryinfo;
uts-nativepage -> uts.sdk.modules.utsNativepage
Example file location in hello uts:
~\uni_modules\uts-nativepage\utssdk\app-android\res
In addition to the layout and values directories listed here, it also supports all android standard resource directories such as anim
需要注意的是:如果res资源中使用了 android appcompat库内置的资源,需要在config.json中添加下面的配置:
{
"dependencies": [
"androidx.appcompat:appcompat:1.0.0"
]
}
Take the uts-advance plugin in hello UTS as an example.
key code:
// Get the asset manager
let assetManager = getAppContext()!.getAssets();
// load free.mp3 resource
let afd = assetManager.openFd("free.mp3");
// Use the media components that come with android to play
let mediaPlayer = new MediaPlayer();
mediaPlayer.setDataSource(afd.getFileDescriptor(),afd.getStartOffset(), afd.getLength());
mediaPlayer.prepare();
mediaPlayer.start();
The location of the complete code in hello uts:
~\uni_modules\uts-advance\utssdk\app-android\assets
下面是一个config.json
示例
{
"dependencies": [
"androidx.recyclerview:recyclerview:1.0.0"
]
}
截止 HBuilder 3.8.2 版本内置了以下依赖
Developers need to pay attention to two points when using the dependencies in the list:
+--- my-imageloader.jar
+--- my-nineoldandroids-2.4.0.jar
+--- zip4j-2.8.0.jar
+--- com.github.getActivity:XXPermissions:18.0@jar
+--- android-gif-drawable-release@1.2.23.aar
+--- msa_mdid_1.0.13.aar
+--- breakpad-build-release.aar
+--- androidx.multidex:multidex:2.0.0@aar
+--- androidx.recyclerview:recyclerview:1.0.0@aar
+--- androidx.legacy:legacy-support-v4:1.0.0@aar
+--- androidx.appcompat:appcompat:1.0.0@aar
+--- com.github.bumptech.glide:glide:4.9.0@aar
+--- com.alibaba:fastjson:1.1.46.android@jar
+--- androidx.fragment:fragment:1.0.0@aar
+--- androidx.vectordrawable:vectordrawable-animated:1.0.0@aar
+--- androidx.legacy:legacy-support-core-ui:1.0.0@aar
+--- androidx.media:media:1.0.0@aar
+--- androidx.legacy:legacy-support-core-utils:1.0.0@aar
+--- androidx.vectordrawable:vectordrawable:1.0.0@aar
+--- androidx.viewpager:viewpager:1.0.0@aar
+--- androidx.coordinatorlayout:coordinatorlayout:1.0.0@aar
+--- androidx.drawerlayout:drawerlayout:1.0.0@aar
+--- androidx.slidingpanelayout:slidingpanelayout:1.0.0@aar
+--- androidx.customview:customview:1.0.0@aar
+--- androidx.swiperefreshlayout:swiperefreshlayout:1.0.0@aar
+--- androidx.asynclayoutinflater:asynclayoutinflater:1.0.0@aar
+--- androidx.loader:loader:1.0.0@aar
+--- androidx.core:core:1.0.0@aar
+--- androidx.versionedparcelable:versionedparcelable:1.0.0@aar
+--- androidx.collection:collection:1.0.0@jar
+--- androidx.cursoradapter:cursoradapter:1.0.0@aar
+--- com.github.bumptech.glide:gifdecoder:4.9.0@aar
+--- androidx.lifecycle:lifecycle-runtime:2.0.0@aar
+--- androidx.interpolator:interpolator:1.0.0@aar
+--- androidx.documentfile:documentfile:1.0.0@aar
+--- androidx.localbroadcastmanager:localbroadcastmanager:1.0.0@aar
+--- androidx.print:print:1.0.0@aar
+--- androidx.lifecycle:lifecycle-viewmodel:2.0.0@aar
+--- androidx.lifecycle:lifecycle-livedata:2.0.0@aar
+--- androidx.lifecycle:lifecycle-livedata-core:2.0.0@aar
+--- androidx.lifecycle:lifecycle-common:2.0.0@jar
+--- androidx.arch.core:core-runtime:2.0.0@aar
+--- androidx.arch.core:core-common:2.0.0@jar
+--- androidx.annotation:annotation:1.0.0@jar
+--- com.github.bumptech.glide:disklrucache:4.9.0@jar
\--- com.github.bumptech.glide:annotations:4.9.0@jar
目前云打包机支持下面的仓库:
jcenter()
google()
// huawei
maven {url 'https://developer.huawei.com/repo/'}
// jitpack 远程仓库:https://jitpack.io
maven { url 'https://jitpack.io' }
部分场景下,开发者可能需要将本地依赖,上传到远程仓库,避免wgt提交资源过大超出打包限制。
这种情况,推荐开发者上传到 jitpack.io 这也是目前android 原生开发主流的远程仓库。 使用文档
In uts, all APIs of Android can be accessed.
However, application and activity are often rewritten in Android development, and the uni-app main engine has rewritten related classes. So if you want to operate application and activity, you need to call the API encapsulated by uni-app engine.
These APIs are UTSAndroid objects under io.dcloud.uts
library, see below for details.
HBuilderX 3.6.3+
import { UTSAndroid } from "io.dcloud.uts";
Usage instructions: Get the current application context, corresponding to the android platform Context.getApplicationContext function implementation
In Android development scenarios, this context is required to call application-level resources/capabilities. For more usage, refer to Android Official Documentation
// [Example] Get the audio under asset and play it
let assetManager = UTSAndroid.getAppContext()!.getAssets();
let afd = assetManager.openFd("free.mp3");
let mediaPlayer = new MediaPlayer();
mediaPlayer.setDataSource(afd.getFileDescriptor(),afd.getStartOffset(), afd.getLength());
mediaPlayer.prepare();
mediaPlayer.start();
** 与Application的转换 **
UTSAndroid.getAppContext() 默认返回的是 实现了 Context
抽象类的Application
对象
部分场景,明确需要 Application
对象,那么直接强制类型转换即可
import Application from 'android.app.Application'
let app = UTSAndroid.getAppContext() as Application
console.log(app)
HBuilderX 3.6.3+
import { UTSAndroid } from "io.dcloud.uts";
Get the runtime absolute path of the specified plugin resource
// [Example] Get the specified resource path
// Get the runtime path of the file: `/storage/emulated/0/Android/data/io.dcloud.HBuilder/apps/__UNI__3732623/www/uni_modules/test-uts-static/static/logo.png`
UTSAndroid.getResourcePath("uni_modules/test-uts-static/static/logo.png")
HBuilderX 3.6.11+
When the App memory is insufficient, the system callback function corresponds to the native API: onTrimMemory
UTSAndroid.onAppTrimMemory((level:Number) => {
let eventName = "onAppTrimMemory - " + level;
console.log(eventName);
});
HBuilderX 3.6.11+
The anti-registration function corresponding to onAppTrimMemory
If the function passed in can be empty, if it is empty, it will be regarded as removing all listeners
// remove all monitors
UTSAndroid.offAppTrimMemory()
// Remove the specified listener
UTSAndroid.offAppTrimMemory((level:Number) => {
});
HBuilderX 3.6.1+
Triggered when the App configuration changes, such as switching between horizontal and vertical screens Corresponding to the native API: onConfigurationChanged
UTSAndroid.onAppConfigChange((ret:UTSJSONObject) => {
let eventName = "onAppConfigChange - " + JSON.stringify(ret);
console.log(eventName);
});
Anti-registration function corresponding to onAppConfigChange
If the function passed in can be empty, if it is empty, it will be regarded as removing all listeners
// remove all monitors
UTSAndroid.offAppConfigChange();
// Remove the specified listener
UTSAndroid.offAppConfigChange(function(ret){
});
Special note: In addition to the functions listed in this chapter, other context methods of the application in the android environment can be implemented through getAppContext()!.xxx()
For example, to get the app cache directory:
UTSAndroid.getAppContext()!.getExternalCacheDir()!.getPath()
HBuilderX 3.6.11+
Get the activity instance to which the current plug-in belongs, corresponding to the android platform getActivity function implementation
In the Android development scenario, this context needs to be used to invoke activity-level resources/capabilities. For more usage, refer to Android Official Documentation
// [示例]获取当前activity顶层容器
let decorView = UTSAndroid.getUniActivity()!.window.decorView;
let frameContent = decorView.findViewById<FrameLayout>(android.R.id.content)
HBuilderX 3.6.3+
Triggered when App's activity onPause
UTSAndroid.onAppActivityPause(() => {
let eventName = "onAppActivityPause - " + Date.now();
console.log(eventName);
});
HBuilderX 3.6.9+
The anti-registration function corresponding to onAppActivityPause
If the function passed in can be empty, if it is empty, it will be regarded as removing all listeners
// remove all monitors
UTSAndroid.offAppActivityPause();
// Remove the specified listener
UTSAndroid.offAppActivityPause(() => {
});
HBuilderX 3.6.3+
Triggered when App's activity onResume
UTSAndroid.onAppActivityResume(() => {
let eventName = "onAppActivityResume - " + Date.now();
console.log(eventName);
});
HBuilderX 3.6.9+
The anti-registration function corresponding to onAppActivityResume
If the function passed in can be empty, if it is empty, it will be regarded as removing all listeners
// remove all monitors
UTSAndroid.onAppActivityResume();
// Remove the specified listener
UTSAndroid.onAppActivityResume(() => {
});
HBuilderX 3.6.3+
Triggered when App's activity onDestroy
UTSAndroid.onAppActivityDestroy(() => {
let eventName = "onAppActivityDestroy- " + Date.now();
console.log(eventName);
});
HBuilderX 3.6.9+
Anti-registration function corresponding to onAppActivityDestroy
If the function passed in can be empty, if it is empty, it will be regarded as removing all listeners
// remove all monitors
UTSAndroid.offAppActivityDestroy();
// Remove the specified listener
UTSAndroid.offAppActivityDestroy(() => {
});
HBuilderX 3.6.3+
Triggered when the App's activity falls back to a physical button click
UTSAndroid.onAppActivityBack(() => {
let eventName = "onAppActivityBack- " + Date.now();
console.log(eventName);
});
HBuilderX 3.6.9+
The anti-registration function corresponding to onAppActivityBack
If the function passed in can be empty, if it is empty, it will be regarded as removing all listeners
// remove all monitors
UTSAndroid.offAppActivityBack();
// Remove the specified listener
UTSAndroid.offAppActivityBack(() => {
});
HBuilderX 3.6.8+
App 的 activity 启动其他activity的回调结果监听 对应原生的 onActivityResult
需要特别注意的是 requestCode
参数,这个参数用于区别 不同的请求来源,开发者应该只处理自己发起请求
let customRequestCode = 12000
UTSAndroid.onAppActivityResult((requestCode: Int, resultCode: Int, data?: Intent) => {
if(requestCode == 12000){
// 我们发起的请求
let eventName = "onAppActivityResult - requestCode:" + requestCode + " -resultCode:"+resultCode + " -data:"+JSON.stringify(data);
console.log(eventName);
}else{
// 别的代码发起的请求,不要处理
}
});
HBuilderX 3.6.9+
The anti-registration function corresponding to onAppActivityResult
If the function passed in can be empty, if it is empty, it will be regarded as removing all listeners
// remove all monitors
UTSAndroid.offAppActivityResult();
// Remove the specified listener
UTSAndroid.offAppActivityResult(() => {
});
已废弃,请使用 4.4章节系统权限管理替代此api
HBuilderX 3.6.3+
App's activity gets the callback of permission request result
UTSAndroid.onAppActivityRequestPermissionsResult((requestCode: number,
permissions: Array<string>,
grantResults: Array<number>) => {
console.log(grantResults);
console.log(permissions);
console.log(requestCode);
});
//发起定位权限申请
let permission = [Manifest.permission.ACCESS_COARSE_LOCATION]
ActivityCompat.requestPermissions(getUniActivity()!,
permission, 1001);
HBuilderX 3.6.9+
The anti-registration function corresponding to onAppActivityRequestPermissionsResult
If the function passed in can be empty, if it is empty, it will be regarded as removing all listeners
// remove all monitors
UTSAndroid.offAppActivityRequestPermissionsResult();
// Remove the specified listener
UTSAndroid.offAppActivityRequestPermissionsResult(() => {
});
-----------------------------
特别说明:除了本章节列出的函数外,android环境下 activity 其他上下文方法都可以通过 getUniActivity()!.xxx()的方式实现
比如获取当前activity的顶层View容器
```ts
UTSAndroid.getUniActivity()!.getWindow().getDecorView();
即使在android原生开发中,应用的生命周期管理也是十分重要的。 android生命周期
UTS环境中对原生的生命周期进行了封装和简化,用户不需要关心 除了activity 以外的更多原生细节。
只需要了解本章节中列出的 activity相关生命周期即可。即 在UTS环境中 开发者可以认为 activity 的生命周期 就是应用的生命周期。
其中最为常见的场景,要数onAppActivityDestroy
中释放系统资源了:
举个例子,以Hello UTS 用户截屏插件为例。
在注册监听回调时,添加了下列代码。
UTSAndroid.onAppActivityDestroy(function(){
screenOB?.stopWatching()
screenOB = null
})
这段代码的意思是当宿主activity被销毁时,主动回收屏幕监听的FileObserver
这是因为除了正常的用户注册/注册 之外,还存在一种情况:用户没有反注册,便关闭了应用。 此时FileObserver 并没有被反注册回收。就会导致应用关闭后继续持有上一个uni-app js引擎实例的引用,从而导致下一次启动时出现引擎回调找不到的情况。
开发者在开发UTS插件时,如果遇到了类似使用系统组件的情况,也需要特别关注资源释放情况。
HBuilder X 3.8.2版本之后支持
系统权限管理使用了 https://github.com/getActivity/XXPermissions 工具库
如果开发者使用了相同依赖,可能打包冲突。需要修改为 complileOnly 或者 修改为本章节内置API
请求系统权限,对应的两个参数: 1 请求的权限列表 2 请求结果回调
let permission = ["android.permission.ACCESS_FINE_LOCATION","android.permission.ACCESS_FINE_LOCATION"]
UTSAndroid.requestSystemPermission(UTSAndroid.getUniActivity()!,permission,function(allRight:boolean,grantedList:string[]){
if(allRight){
// 用户同意了全部权限
}else{
// 用户仅同意了 grantedList中的权限
}
},function(doNotAskAgain:boolean,grantedList:string[]){
// 用户拒绝了部分权限,仅允许了grantedList中的权限
if(doNotAskAgain){
// 用户拒绝了权限,并且选择不再询问
}
})
跳转至系统设置权限设置界面,一般是用户选择了不再继续询问选项后
let permissionWifi = ["android.permission.ACCESS_FINE_LOCATION", "android.permission.ACCESS_FINE_LOCATION"]
UTSAndroid.gotoSystemPermissionActivity(UTSAndroid.getUniActivity()!,permissionWifi)
判断权限是否已经被用户禁止
let permission = ["android.permission.ACCESS_FINE_LOCATION", "android.permission.ACCESS_FINE_LOCATION"]
let denied = UTSAndroid.getSystemPermissionDenied(UTSAndroid.getUniActivity()!, permission)
// 执行结果
[android.permission.ACCESS_FINE_LOCATION, android.permission.ACCESS_FINE_LOCATION]
判断权限是否已经被用户授予
let permission = ["android.permission.ACCESS_FINE_LOCATION", "android.permission.ACCESS_FINE_LOCATION"]
let grant = UTSAndroid.checkSystemPermissionGranted (UTSAndroid.getUniActivity()!, permission)
// 执行结果
false
通过上面的章节的阅读。
至此我们认为你已经掌握了UTS语法,掌握了基本的Kotlin语法,掌握了UTS对于android资源的支持。
但是对于一个熟悉android开发的kotlin语言者来说,有很多常用的习惯发生了改变,我们会在这个章节特别指出,便于开发者加深认识。
kotlin中可为空的语法统一为类型后加?
,以下面的代码为例
// A nullable string variable named user
var user:String? = null
但是ts中分两种情况,如果是全局变量,可为空,需要这样写
let user:string | null
如果是成员变量,与kotlin类似,但是区别在于?写在变量后,而非类型后
let user?:string
kotlin
中 可变变量修饰为 var
、val
。 区别在于 val 不可变,var可变。
uts
中对应var
的变量类型为 var/let
推荐使用let
因为只会在作用域内生效,需要慎用var
,因为它具备有更大的作用范围
方法定义 kotlin
里的方法只有一种定义方式
fun startListener():void{
}
uts中,需要区分全局方法、成员方法
// member method
startListener():void{
}
// global method
function startListener():void{
}
kotlin
中的: 继承操作符,需要用extends
取代
语法 | kotlin | uts |
---|---|---|
继承类 | : | extends |
实现type接口 | : | extends |
实现接口 | : | implements |
// 使用UTS 实现 OnClickListener接口
class StartServiceListener extends OnClickListener{
override onClick(v?: View):void{
// 执行点击逻辑
}
}
kotlin中的非空断言是!!
,ts中是一个!
user!.sayHello();
user!!.sayHello();
//kotlin 中快速实现super
constructor() : super() {
}
//uts 中快速实现super
constructor (){
super();
}
kotlin
中可以使用匿名内部类
// kotlin new event listener
user.setListener(Listener(){
//todo
});
目前版本UTS还不支持匿名内部类,需要显性的声明再新建
// Declare a new class that implements Listener
class MyListener extends Listener{
// todo
}
// Create a new instance
let myListener = new MyListener();
user.setListener(myListener);
有一种特殊场景,我们需要定义一些可为空的函数变量,比如下面的 success,fail:
type Option = {
success?: (res: object) => void;
fail?: (res: object) => void;
};
这个时候我们需要这样调用
options.success?.(res)
这样的调用方式在kotlin中是非法的,属于TS中的特有语法,需要特别注意。
在Kotlin
/java
中允许一个函数有多个构造器,但是UTS中是不被允许的
android开发中场景的 intent跳转需要传入 目标界面的class对象,目前UTS中仅支持一种写法
let intent = new Intent(getUniActivity(),DemoActivity().javaClass);
getUniActivity()!.startActivity(intent);
某些场景下开发者需要获得 指定double数据类型的数据
开发者下意识的写法可能是:
// this is wrong
let a:Int =3
let b:Int =4
let c:Double = a/b
但是Android原生环境中,数据类型的精度是向下兼容的,如果想要获得一个double类型,必须要有一个double类型参与运算:
// This is correct
let a:Int =3
let b:Int =4
let c:Double = a * 1.0 / b
下面的内容不会影响功能使用,但是在UTS环境中,有合适的解决办法
kotlin
或者java
中java.lang.*是被特殊处理的,可以直接使用而不需要引入。
// Get the current timestamp
System.currentTimeMillis()
UTS环境中,lang包没有被特殊对待,需要手动引入。
// Manually import the classes under the lang package
import System from 'java.lang.System';
// Get the current timestamp
System.currentTimeMillis()
UTS
不建议使用 快捷构造kotlin
中 支持通过()的方式,快速实现无参构造器的声明
// Get the current timestamp
class ScreenReceiver extends BroadcastReceiver(){
}
UTS环境中,不建议这样做(虽然目前这样做不会影响编译),建议使用手动声明无参构造
class ScreenReceiver extends BroadcastReceiver{
constructor (){
super();
}
}
UTS
中下划线前缀的变量,有屏蔽未使用警告的含义// IDE will prompt that name, status, desc variables are not used
onStatusUpdate(name:string, status:Int, desc:string){
}
// don't warn about variable unused
onStatusUpdate(_name:string, _status:Int, _desc:string){
}
activity
?参考Hello UTS项目中的uts-nativepage插件
路径:
~\uni_modules\uts-nativepage
service
?参考Hello UTS项目中的uts-nativepage插件
路径:
~\uni_modules\uts-nativepage
Thread
?简单示例
class CustomThread extends Thread{
constructor(){
super();
}
override run(){
Thread.sleep(1000)
console.log("CustomThread = " + Thread.currentThread().getName())
}
}
完整示例参考Hello UTS项目中的uts-nativepage插件
路径:
~\uni_modules\uts-nativepage
因为android中,每个UTS插件都对应一个gradle 子项目,所以类似的情况不能简单复用 自定义基座中的官方依赖。
需要: 不要勾选官方的依赖,然后在uts插件中,按照文档配置依赖
UTSCallback 和 UTSJSONObject 是UTS内置专门用于UTS环境和前端交互的特定类型。
uni环境与UTS环境交互时,除了基本数据类型之外,涉及function的需要使用UTSCallback替代,涉及复杂对象object需要用UTSJSONObject 替代
UTS环境中,默认的数组写法[] / Array() 对应到 android平台的数据结构是 UTSArray
理论上来说 UTSArray
确实更加灵活强大,但是部分android 平台api 明确要求了 Array格式的数据(比如请求权限)
类似场景下,我们就要使用 toTypedArray() 函数进行转换,以便将MutableList
转换为对应的Array
// 得到一个UTSArray
let permissionArray :String[] = []
// 得到一个Array
console.log(permissionArray.toArray())
// 得到一个MutableList
console.log(permissionArray.toMutableList())
另外还存在一种特殊情况,即开发者 在UTS中使用了 kotlin
编写的依赖,这个时候情况稍微复杂些
与UTS
中只有一种 数组结构相比,kotlin
中的数组结构要多很多,比如 IntArray
,Array
,MutableList
等,
对于情况,开发者需要注意两点:
1 UTS具备类型推导功能,调用第三方依赖是不需要声明类型
// 建议的写法
let a:IntArray = xxx.getInfo()
// 这样是没必要的,如果一定要这样写,必须要明确了解到kotlin依赖返回的数据结构,否能可能会因为类型错误,导致编译报错
let a:IntArray = xxx.getInfo()
2 各种数组类型的转换说明
// IntArray 转 MutableList
val a = intArrayOf(1,2,3)
val b = a.toMutableList()
// MutableList 转 Array<Int>
val c = b.toTypedArray()
// Array<Int> 转 IntArray
val d = c.toIntArray()
在java平台中,二进制操作一般采用字节数组实现。
UTS在android平台编译后的语言为Kotlin,对应的语法对象是ByteArray.
使用这个类不需要额外引入包,直接运行即可
下面是一个简单的示例
let byteTest = new ByteArray(5)
console.log(byteTest)
在 uni-app 1.0 平台,js环境与原生环境的交互都是经过js引擎桥接
js引擎除了 string,number,boolean 等基本数据结构外,仅支持JSONObject,JSONArray两种。
下面是一个Array的使用示例:
// UTS插件,声明数组参数
export function callWithoutParam(filterArray : Array<string>,success: () => void) {
console.log(filterArray)
success();
return { name: "doSthWithCallback" };
}
// 前端传递数组参数
UTSHello.callWithoutParam(
["system","optionB"]
,
()=>{
uni.showToast({
icon:'none'
});
}
);
UTS插件支持使用android的原生资源,比如动画,布局,字符串等。 详细说明
如果提示 R资源无法找到:unresolved reference R
1 需要排查资源是否符合android原生格式
2 检查R资源引入的包名是否正确,参考hello uts nativepage插件
import R from 'io.dcloud.uni_modules.uts_nativepage.R';
val extraParam = UTSJSONObject()
val extraMap = extraParam.toMap()
前端领域里线程安全的解决思路 与java的不同。 他们提供了 async/await 等关键字来实现异步任务处理
如果业务代码中有需要多线程、异步任务,建议切换到 async/await 等 uts 语法
如果是要翻译原有的java代码到 UTS,可以选择打成AAR来处理。
简单类型判断,返回结果 string/number/object/function 等
let param = "123"
UTSAndroid.typeOf(param) // string
复杂的对象类名判断
let aa = 12
// 可以获取到具体的类名
console.log(aa.javaClass.toString()) // int
相比于for in / 下标计数等写法, UTS 推荐更现代化的foreach语法 实现集合的遍历。
数组:
let arrayObj = utsArrayOf("111","222","333")
arrayObj.forEach(function(e:any){
console.log(e)
})
let arrayObj2 = [10,20,30]
arrayObj2.forEach(function(e:any){
console.log(e)
})
遍历Map:
let mapObj = new Map<string,any>()
mapObj.put("name","zhangsan")
mapObj.put("age",12)
mapObj.forEach(function(value:any,key:string){
console.log(key)
console.log(value)
})
遍历UTSJSONObject:(暂未公开)
let utsJsonObj = {
name:"zhangsan",
age:"22",
}
utsJsonObj.forEach(function(perField:any){
console.log(perField)
})
以HelloUTS nativepage插件 部分代码为例:
import OnClickListener from 'android.view.View.OnClickListener';
// 实现 OnClickListener 接口
class User {
name:string = "name"
}
class StartBroadcastListener extends User implements OnClickListener{
override onClick(v?: View):void{
let myReceiver = new ScreenReceiver();
let filter = new IntentFilter();
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_SCREEN_ON);
UTSAndroid.getUniActivity()!.registerReceiver(myReceiver, filter);
// 提示屏幕状态监听已经注册
Toast.makeText(UTSAndroid.getAppContext(),"屏幕状态监听已注册,注意观察控制台日志",Toast.LENGTH_LONG).show();
}
}
// 使用
let btn_start_screen_listen = this.findViewById<Button>(R.id.btn_start_screen_listen);
btn_start_screen_listen.setOnClickListener(new StartBroadcastListener());
如果要同时实现多个接口,采用的也是 implements 和 ,
分隔来实现
class Person{
name:string = ""
}
class User extends Person implements android.view.View.OnClickListener,Cloneable{
constructor(){
}
override onClick(v?: android.view.View):void{
console.log(v)
}
override equals(other?: any):boolean{
return true
}
}
编译后的kotlin代码
open class Person {
open var name: String = "";
}
open class User : Person, android.view.View.OnClickListener, Cloneable {
constructor(){}
override fun onClick(v: android.view.View?): Unit {
console.log(v, " at uni_modules/uts-helloworld/utssdk/index.uts:37");
}
override fun equals(other: Any?): Boolean {
return true;
}
}
其中需要注意的是
当以type 结构体为参数时,其内部boolean字段 默认值为false,不支持指定。
HBuilderX 3.7.1 版本已支持
建议先使用7.X版本,这个问题后续会处理
比如xml布局文件中暂时只支持 linearlayout等官方标签,不支持 appcompat等三方库标签。这个问题后续会被处理