uniapp使用uts插件启动原生安卓Service
背景
在上一篇文章中uniapp使用uts插件调用原生API,我们使用uts插件来实现了一个简单的例子来调用原生安卓平台的Toast。今天我们继续使用uts插件来实现一个稍微复杂点的例子,启动一个原生安卓平台的Service,通常在安卓平台,启动一个前台服务,能增加我们APP存活的几率。
实现
本次实现就继续在上一篇基础的uts插件上进行开发,如果还没有看过上一篇文章,请移步查看。
首先我们回忆下安卓平台使用原生开发语言Java/Kotlin怎么来启动一个前台服务。
1、自定义一个类来继承Service。
2、重载onCreate、onBind、onStartCommand、onDestroy等方法。
3、启动一个通知栏常驻通知。
接下来我们就用uts语法来实现以上三个步骤,这里就直接贴代码:
javascript
class ForeService extends Service {
//无参构造,必须要
constructor (){
super();
}
override onCreate() : void {
super.onCreate();
console.log("onCreate");
initNotification()
}
override onBind(_intent?: Intent): IBinder|null{
console.log("onBind");
return null;
}
override onStartCommand(intent:Intent ,flags:Int ,startId:Int ):Int{
console.log("onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
override onDestroy():void {
console.log("onDestroy");
super.onDestroy();
// this.stopSelf()
}
//前台服务常驻通知栏
initNotification(){
let mBuilder = new NotificationCompat.Builder(this,"uts-test");
// 点击后让通知将消失
mBuilder.setAutoCancel(true)
mBuilder.setContentText("测试")
mBuilder.setContentTitle("测试")
//通知产生的时间,会在通知信息里显示
mBuilder.setWhen(System.currentTimeMillis())
//设置该通知优先级
mBuilder.setPriority(NotificationManager.IMPORTANCE_DEFAULT)
//ture,设置他为一个正在进行的通知。他们通常是用来表示一个后台任务,用户积极参与(如播放音乐)或以某种方式正在等待,因此占用设备(如一个文件下载,同步操作,主动网络连接)
mBuilder.setOngoing(false)
//向通知添加声音、闪灯和振动效果的最简单、最一致的方式是使用当前的用户默认设置,使用defaults属性,可以组合:
mBuilder.setDefaults(Notification.DEFAULT_ALL)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
let manager =
UTSAndroid.getAppContext()!.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
let channelId = "channelId" + System.currentTimeMillis()
let channel = new NotificationChannel(
channelId,
"appName",
NotificationManager.IMPORTANCE_HIGH
)
manager.createNotificationChannel(channel)
mBuilder.setChannelId(channelId)
}
mBuilder.setContentIntent(null)
this.startForeground(102, mBuilder.build())
}
}
注意,我们还需要导入所使用的SDK中的类,后续会统一贴出。
接下来,我们还需要暴露出两个函数用来启动服务和停止服务。熟悉原生开发的同学肯定知道启动服务需要Context上下文对象,这里uniapp已经内置了,直接使用UTSAndroid.getUniActivity()即可获取,然后Class对象则使用UTSAndroid.getJavaClass来获取。最后提出index.uts中的完整代码:
javascript
import Context from 'android.content.Context';
import Toast from 'android.widget.Toast';
import Intent from 'android.content.Intent';
import Service from "android.app.Service";
import IBinder from 'android.os.IBinder';
import NotificationCompat from 'androidx.core.app.NotificationCompat';
import NotificationManager from 'android.app.NotificationManager';
import NotificationChannel from 'android.app.NotificationChannel';
import Notification from 'android.app.Notification';
import Build from 'android.os.Build';
import System from 'java.lang.System';
//这里用作启动服务后的回调
export type ServiceOptions = {
success?: (res: object) => void
stop?: (res: object) => void
}
//停止服务
export function stopService() : void {
console.log('stopService',UTSAndroid.getJavaClass(ForeService()).name)
let intent = new Intent(UTSAndroid.getUniActivity(), UTSAndroid.getJavaClass(ForeService()));
UTSAndroid.getAppContext()!.stopService(intent);
}
//启动服务
export function startService(options: ServiceOptions) : void {
let intent = new Intent(UTSAndroid.getUniActivity(), UTSAndroid.getJavaClass(ForeService()));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
console.log('startForegroundService')
UTSAndroid.getAppContext()!.startForegroundService(intent);
}else{
console.log('startService')
UTSAndroid.getAppContext()!.startService(intent);
}
//启动成功后的回到,我们这里默认调用了startService后就成功启动服务
options.success?.({
msg: "success"
})
}
class ForeService extends Service {
constructor (){
super();
}
override onCreate() : void {
super.onCreate();
console.log("onCreate");
initNotification()
}
override onBind(_intent?: Intent): IBinder|null{
console.log("onBind");
return null;
}
override onStartCommand(intent:Intent ,flags:Int ,startId:Int ):Int{
console.log("onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
override onDestroy():void {
console.log("onDestroy");
super.onDestroy();
// this.stopSelf()
}
initNotification(){
let mBuilder = new NotificationCompat.Builder(this,"uts-test");
// 点击后让通知将消失
mBuilder.setAutoCancel(true)
mBuilder.setContentText("测试")
mBuilder.setContentTitle("测试")
//通知产生的时间,会在通知信息里显示
mBuilder.setWhen(System.currentTimeMillis())
//设置该通知优先级
mBuilder.setPriority(NotificationManager.IMPORTANCE_DEFAULT)
//ture,设置他为一个正在进行的通知。他们通常是用来表示一个后台任务,用户积极参与(如播放音乐)或以某种方式正在等待,因此占用设备(如一个文件下载,同步操作,主动网络连接)
mBuilder.setOngoing(false)
//向通知添加声音、闪灯和振动效果的最简单、最一致的方式是使用当前的用户默认设置,使用defaults属性,可以组合:
mBuilder.setDefaults(Notification.DEFAULT_ALL)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
let manager =
UTSAndroid.getAppContext()!.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
let channelId = "channelId" + System.currentTimeMillis()
let channel = new NotificationChannel(
channelId,
"appName",
NotificationManager.IMPORTANCE_HIGH
)
manager.createNotificationChannel(channel)
mBuilder.setChannelId(channelId)
}
mBuilder.setContentIntent(null)
this.startForeground(102, mBuilder.build())
}
}
到这里全部完成了么?no,no,no,还记得上篇文章中我们提到的AndroidManifest.xml文件么?这里派上了用场,我们还需要注册我们的服务(安卓中四大组件必须在AndroidManifest.xml中注册)。
javascript
<?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="uts.sdk.modules.myToast">
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<application>
<service android:name="uts.sdk.modules.myToast.ForeService" android:exported="true"/>
</application>
</manifest>
这里service包名前缀为uts.sdk.modules不可改动,因为我们是modules形式插件,然后myToast是你插件命名的驼峰标识,最后名字则是自定义的Service类名,包名不对会导致无法正确启动服务。
在vue页面中调用就很简单了,放两个按钮,然后引入插件中的startService和stopService函数。
javascript
<template>
<view class="content">
<image class="logo"
src="/static/logo.png"
@click="handleStart"></image>
<image class="logo"
src="/static/logo.png"
@click="handleStop"></image>
</view>
</template>
<script>
//引入函数
import {
startService,
stopService
} from "@/uni_modules/my-toast"
export default {
data() {
return {
title: 'Hello',
interval: null
}
},
onLoad() {
},
methods: {
handleStart(){
startService({
success: res=> {
console.log(res)
this.interval = setInterval(() => {
console.log('task is running...')
}, 10000)
}
})
},
handleStop(){
if(this.interval){
clearInterval(this.interval)
this.interval = null
}
stopService()
}
}
}
</script>
<style>
.content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.logo {
height: 200rpx;
width: 200rpx;
margin-top: 200rpx;
margin-left: auto;
margin-right: auto;
margin-bottom: 50rpx;
}
.text-area {
display: flex;
justify-content: center;
}
.title {
font-size: 36rpx;
color: #8f8f94;
}
</style>
点击靠上的按钮启动服务,我们看下运行效果图:
可以看到我们前台服务已经启动,你可以在回调中执行你的任务。这里需要注意的是因为需要常驻通知栏,需要去设置中授权应用通知权限。
尾巴
今天的文章就到这里,本篇文章和上一篇uniapp使用uts插件调用原生API有较强关联,建议先看上一篇文章在看这篇文章。有问题可以给我留言,希望能帮助到有需要的人。如果你喜欢我的文章欢迎给我点赞,谢谢!