提交 f1216826 编写于 作者: DCloud-yyl's avatar DCloud-yyl

Merge branch 'dev' into alpha

......@@ -21,6 +21,7 @@
<button @tap="testoffMemoryWarning">关闭内存不足告警监听</button>
<button @tap="getLocationTest" style="width: 100%;">获取定位</button>
<button type="default" @click="handleInstallApk">安装apk</button>
<button type="default" @click="handleShowNotificationProgress">显示通知栏下载进度</button>
</view>
</template>
......@@ -30,6 +31,12 @@
installApk
} from "@/uni_modules/uni-installApk"
let pre = 0
let speed = 1
let preTime = 0
let isBegin = false
export default {
data() {
return {
......@@ -291,6 +298,63 @@
}
})
},
handleShowNotificationProgress(){
const task = uni.downloadFile({
url: "http://192.168.213.108:8080/test.apk",
success(e) {
console.log("success111 :", e);
uni.finishNotificationProgress({
title: "安装升级包",
content: "下载完成。",
callback: () => {
uni.installApk({
filePath: e.tempFilePath,
complete(res) {
console.log(res);
}
})
}
})
},
fail(e) {
console.log("fail : ", e);
}
});
task.onProgressUpdate((res) => {
const sd = this.calculateSpeed(res.totalBytesWritten)
const remian = ((res.totalBytesExpectedToWrite - res.totalBytesWritten) / sd).toFixed(0)
const remianStr = sd != 1 ? "剩余时间 " + remian + "" : "正在计算"
uni.createNotificationProgress({
title: "正在下载升级包",
content: remianStr,
progress: res.progress
})
if (res.progress == 100) {
pre = 0
speed = 1
preTime = Date.now()
isBegin = false
}
})
},
calculateSpeed(current) {
//简略的计算下载速度
if (!isBegin) {
preTime = Date.now()
isBegin = true
return speed
}
const currentTime = Date.now()
if (currentTime - preTime > 1000) {
speed = current - pre
pre = current
preTime = currentTime
}
return speed
}
}
}
</script>
......
import { ExitOptions, ExitSuccess, ExitCompleteCallback, Exit } from "../interface.uts"
import { ExitOptions, ExitSuccess, Exit } from "../interface.uts"
/**
......
import { ExitOptions, ExitFailCallback, ExitCompleteCallback, Exit} from "../interface.uts"
import { ExitOptions, Exit} from "../interface.uts"
import { ExitFailImpl } from "../unierror.uts"
......
......@@ -25,6 +25,7 @@ export const UniErrors:Map<number, string> = new Map([
* ExitFail的实现
*/
export class ExitFailImpl extends UniError implements IExitError {
override errCode: ExitErrorCode
constructor (
errCode: ExitErrorCode
) {
......
## 1.0.4(2023-12-08)
兼容asset目录文件的处理
## 1.0.3(2023-10-27)
遵循UniError规范
## 1.0.2(2023-10-27)
......
{
"id": "uni-installApk",
"displayName": "uni-installApk",
"version": "1.0.3",
"version": "1.0.4",
"description": "uni-installApk",
"keywords": [
"uni-installApk"
......
......@@ -6,12 +6,20 @@ import File from 'java.io.File';
import FileProvider from 'androidx.core.content.FileProvider';
import Context from 'android.content.Context';
import Uri from 'android.net.Uri';
import FileOutputStream from 'java.io.FileOutputStream';
export function installApk(options : InstallApkOptions) : void {
const context = UTSAndroid.getAppContext() as Context
const filePath = UTSAndroid.convert2AbsFullPath(options.filePath)
const apkFile = new File(filePath)
if (!apkFile.exists() && !apkFile.isFile()) {
var filePath = UTSAndroid.convert2AbsFullPath(options.filePath)
var apkFile : File | null = null;
if (filePath.startsWith("/android_asset/")) {
filePath = filePath.replace("/android_asset/", "")
apkFile = copyAssetFileToPrivateDir(context, filePath)
} else {
apkFile = new File(filePath)
}
if (apkFile != null && !apkFile.exists() && !apkFile.isFile()) {
let error = new InstallApkFailImpl(1300002);
options.fail?.(error)
options.complete?.(error)
......@@ -23,11 +31,11 @@ export function installApk(options : InstallApkOptions) : void {
if (Build.VERSION.SDK_INT >= 24) {
const authority = context.getPackageName() + ".dc.fileprovider"
const apkUri = FileProvider.getUriForFile(context, authority, apkFile)
const apkUri = FileProvider.getUriForFile(context, authority, apkFile!!)
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
} else {
intent.setDataAndType(Uri.fromFile(apkFile), "application/vnd.android.package-archive");
intent.setDataAndType(Uri.fromFile(apkFile!!), "application/vnd.android.package-archive");
}
context.startActivity(intent)
......@@ -37,3 +45,39 @@ export function installApk(options : InstallApkOptions) : void {
options.success?.(success)
options.complete?.(success)
}
function copyAssetFileToPrivateDir(context : Context, fileName : string) : File | null {
try {
const destPath = context.getCacheDir().getPath() + "/apks/" + fileName
const outFile = new File(destPath)
const parentFile = outFile.getParentFile()
if (parentFile != null) {
if (!parentFile.exists()) {
parentFile.mkdirs()
}
}
if (!outFile.exists()) {
outFile.createNewFile()
}
const inputStream = context.getAssets().open(fileName)
const outputStream = new FileOutputStream(outFile)
let buffer = new ByteArray(1024);
do {
let len = inputStream.read(buffer);
if (len == -1) {
break;
}
outputStream.write(buffer, 0, len)
} while (true)
inputStream.close()
outputStream.close()
return outFile
} catch (e : Exception) {
e.printStackTrace()
}
return null
}
declare namespace UniNamespace {
interface InstallApkSuccess {
/**
* 安装成功消息
*/
errMsg : string
}
type InstallApkErrorCode = 1300002
interface InstallApkFail {
errCode : InstallApkErrorCode
}
type InstallApkComplete = any
type InstallApkSuccessCallback = (res : InstallApkSuccess) => void
type InstallApkFailCallback = (err : InstallApkFail) => void
type InstallApkCompleteCallback = (res : InstallApkComplete) => void
interface InstallApkOptions {
/**
* apk文件地址
*/
filePath : string,
/**
* 接口调用成功的回调函数
* @defaultValue null
*/
success ?: InstallApkSuccessCallback | null,
/**
* 接口调用失败的回调函数
* @defaultValue null
*/
fail ?: InstallApkFailCallback | null,
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
* @defaultValue null
*/
complete ?: InstallApkCompleteCallback | null
}
}
declare interface Uni {
/**
* installApk()
* @description
* 安装apk
* @param {InstallApkOptions}
* @return {void}
* @uniPlatform {
* "app": {
* "android": {
* "osVer": "4.4",
* "uniVer": "3.94+",
* "unixVer": "3.94+"
* },
* "ios": {
* "osVer": "x",
* "uniVer": "x",
* "unixVer": "x"
* }
* }
* }
* @example
```typescript
uni.installApk({
filePath: "/xx/xx/xx.apk",
complete: (res: any) => {
console.log("complete => " + JSON.stringify(res));
}
});
```
*/
installApk(options : UniNamespace.InstallApkOptions) : void
}
import { UTSAndroid } from "io.dcloud.uts"
import { OnMemoryWarning, OffMemoryWarning } from "../interface.uts"
import { OnMemoryWarning, OffMemoryWarning, MemoryWarningCallback, MemoryWarningCallbackResult } from "../interface.uts"
let listeners: UTSCallback[] = []
let listeners: MemoryWarningCallback[] = []
const onAppTrimMemoryListener = (ret: number) => {
listeners.forEach(listener => {
let res = {
let res: MemoryWarningCallbackResult = {
level:ret
}
listener(res)
......@@ -14,7 +14,7 @@ const onAppTrimMemoryListener = (ret: number) => {
@Suppress("DEPRECATION")
export const onMemoryWarning : OnMemoryWarning = function (callback: UTSCallback) {
export const onMemoryWarning : OnMemoryWarning = function (callback: MemoryWarningCallback) {
if (listeners.length == 0) {
// 仅首次执行底层的实际监听
UTSAndroid.onAppTrimMemory(onAppTrimMemoryListener)
......@@ -28,7 +28,7 @@ export const onMemoryWarning : OnMemoryWarning = function (callback: UTSCallbac
@Suppress("DEPRECATION")
export const offMemoryWarning : OffMemoryWarning = function (callback: UTSCallback | null) {
export const offMemoryWarning : OffMemoryWarning = function (callback: MemoryWarningCallback | null) {
if(callback == null){
// 清除全部回调
......
import { NotificationCenter } from 'Foundation';
import { UIApplication } from "UIKit"
import { Selector } from "ObjectiveC"
import { OnMemoryWarning, OffMemoryWarning } from "../interface.uts"
import { OnMemoryWarning, OffMemoryWarning, MemoryWarningCallback, MemoryWarningCallbackResult } from "../interface.uts"
class MemoryWarningTool {
static listeners: UTSCallback[] = []
static listener: MemoryWarningCallback | null = null
// 监听内存警告
static listenMemoryWarning(callback: UTSCallback) {
static listenMemoryWarning(callback: MemoryWarningCallback) {
// 只有首次才需要注册监听事件
if (this.listeners.length == 0) {
if (this.listener == null) {
// 注册监听内存警告通知事件及设置回调方法
// target-action 回调方法需要通过 Selector("方法名") 构建
const method = Selector("receiveMemoryWarning")
NotificationCenter.default.addObserver(this, selector = method, name = UIApplication.didReceiveMemoryWarningNotification, object = null)
}
this.listeners.push(callback)
this.listener = callback
}
// 内存警告回调的方法
// target-action 的方法前需要添加 @objc 前缀
@objc static receiveMemoryWarning() {
// 触发回调
this.listeners.forEach(listener => {
listener({})
})
let res: MemoryWarningCallbackResult = {
level: 0
};
this.listener?.(res);
}
// 移除监听事件
static removeListen(callback: UTSCallback | null) {
// 移除所有监听
if (callback == null) {
this.listeners = []
// 移除监听事件
static removeListen(callback: MemoryWarningCallback | null) {
this.listener = null;
NotificationCenter.default.removeObserver(this)
return
}
// 清除指定回调
const index = this.listeners.indexOf(callback!)
if (index > -1) {
this.listeners.splice(index, 1)
}
}
}
// 开启监听内存警告
export const onMemoryWarning : OnMemoryWarning = function (callback: UTSCallback) {
export const onMemoryWarning : OnMemoryWarning = function (callback: MemoryWarningCallback) {
MemoryWarningTool.listenMemoryWarning(callback)
}
// 关闭监听内存警告
export const offMemoryWarning : OffMemoryWarning = function (callback: UTSCallback | null) {
export const offMemoryWarning : OffMemoryWarning = function (callback: MemoryWarningCallback | null) {
MemoryWarningTool.removeListen(callback)
}
declare namespace UniNamespace {
interface MemoryWarningCallbackResult {
/**
* 内存警告等级(仅安卓平台有效,iOS始终是0)
*/
level: number
}
/**
* uni.onMemoryWarning/uni.offMemoryWarning回调函数定义
*/
type MemoryWarningCallback = (res: MemoryWarningCallbackResult) => void
type OnMemoryWarning = (callback: MemoryWarningCallback) => void
type OffMemoryWarning = (callback : MemoryWarningCallback | null) => void
}
declare interface Uni {
/**
* 开启监听内存警告
*
* @param {MemoryWarningCallback} callback
* @tutorial https://uniapp.dcloud.net.cn/api/system/memory.html#onmemorywarning
* @uniPlatform {
* "app": {
* "android": {
* "osVer": "4.4.4",
* "uniVer": "3.7.7",
* "unixVer": "3.9.0"
* },
* "ios": {
* "osVer": "9.0",
* "uniVer": "3.7.7",
* "unixVer": "3.9.0"
* }
* }
* }
* @uniVersion 3.7.7
* @uniVueVersion 2,3 //支持的vue版本
* @autotest { expectCallback: true }
*/
onMemoryWarning(callback: UniNamespace.MemoryWarningCallback) : void,
/**
* 取消监听内存不足告警事件
*
* @param {MemoryWarningCallback} callback
* @tutorial https://uniapp.dcloud.net.cn/api/system/memory.html#offmemorywarning
* @uniPlatform {
* "app": {
* "android": {
* "osVer": "4.4.4",
* "uniVer": "3.7.7",
* "unixVer": "3.9.0"
* },
* "ios": {
* "osVer": "9.0",
* "uniVer": "3.7.7",
* "unixVer": "3.9.0"
* }
* }
* }
* @uniVersion 3.7.7
* @uniVueVersion 2,3 //支持的vue版本
* @autotest { expectCallback: true }
*/
offMemoryWarning(callback : UniNamespace.MemoryWarningCallback | null) : void
}
/**
* uni.onMemoryWarning/uni.offMemoryWarning回调参数
*/
export type MemoryWarningCallbackResult = {
/**
* 内存警告等级(仅安卓平台有效,iOS始终是0)
*/
level: number
}
/**
* uni.onMemoryWarning/uni.offMemoryWarning回调函数定义
*/
export type MemoryWarningCallback = (res: MemoryWarningCallbackResult) => void
export type OnMemoryWarning = (callback: UTSCallback) => void
export type OnMemoryWarning = (callback: MemoryWarningCallback) => void
export type OffMemoryWarning = (callback : UTSCallback | null) => void
export type OffMemoryWarning = (callback : MemoryWarningCallback | null) => void
export interface Uni {
/**
* 开启监听内存警告
*
* @param {UTSCallback} callback
* @param {MemoryWarningCallback} callback
* @tutorial https://uniapp.dcloud.net.cn/api/system/memory.html#onmemorywarning
* @uniPlatform {
* "app": {
......@@ -27,11 +41,11 @@ export interface Uni {
* @uniVueVersion 2,3 //支持的vue版本
* @autotest { expectCallback: true }
*/
onMemoryWarning(callback: UTSCallback) : void,
onMemoryWarning(callback: MemoryWarningCallback) : void,
/**
* 取消监听内存不足告警事件
*
* @param {UTSCallback} callback
* @param {MemoryWarningCallback} callback
* @tutorial https://uniapp.dcloud.net.cn/api/system/memory.html#offmemorywarning
* @uniPlatform {
* "app": {
......@@ -51,5 +65,5 @@ export interface Uni {
* @uniVueVersion 2,3 //支持的vue版本
* @autotest { expectCallback: true }
*/
offMemoryWarning(callback : UTSCallback | null) : void
offMemoryWarning(callback : MemoryWarningCallback | null) : void
}
## 1.0.4(2023-11-30)
1. createNotificationProgress增加`onClick`回调
2.修复在小米部分系统上,通知消息会归类于不重要通知的bug
## 1.0.3(2023-11-28)
更新截图
## 1.0.2(2023-11-28)
修改资源的包名
## 1.0.1(2023-11-28)
更新文档
## 1.0.0(2023-11-28)
Android通知栏显示进度插件
{
"id": "uni-progress-notification",
"displayName": "uni-progress-notification",
"version": "1.0.4",
"description": "uni-progress-notification",
"keywords": [
"uni-progress-notification"
],
"repository": "",
"engines": {
"HBuilderX": "^3.91"
},
"dcloudext": {
"type": "uts",
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "插件不采集任何数据",
"permissions": "TargetSDKVersion33以上时需配置\n`android.permission.POST_NOTIFICATIONS`"
},
"npmurl": ""
},
"uni_modules": {
"dependencies": [],
"uni-ext-api": {
"uni": {
"createNotificationProgress": {
"name": "createNotificationProgress",
"app": {
"js": true,
"kotlin": true,
"swift": false
}
},
"finishNotificationProgress": {
"name": "finishNotificationProgress",
"app": {
"js": true,
"kotlin": true,
"swift": false
}
},
"cancelNotificationProgress": {
"name": "cancelNotificationProgress",
"app": {
"js": true,
"kotlin": true,
"swift": false
}
}
}
},
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"Vue": {
"vue2": "y",
"vue3": "y"
},
"App": {
"app-android": {
"minVersion": "19"
},
"app-ios": "n"
},
"H5-mobile": {
"Safari": "n",
"Android Browser": "n",
"微信浏览器(Android)": "n",
"QQ浏览器(Android)": "n"
},
"H5-pc": {
"Chrome": "n",
"IE": "n",
"Edge": "n",
"Firefox": "n",
"Safari": "n"
},
"小程序": {
"微信": "n",
"阿里": "n",
"百度": "n",
"字节跳动": "n",
"QQ": "n",
"钉钉": "n",
"快手": "n",
"飞书": "n",
"京东": "n"
},
"快应用": {
"华为": "n",
"联盟": "n"
}
}
}
}
}
\ No newline at end of file
# uni-download-notification
## 使用说明
Android平台创建显示进度的通知栏消息
**注意: 需要自定义基座,否则点击通知栏消息不会拉起应用**
### uni.createNotificationProgress(options : CreateNotificationProgressOptions) : void,
创建显示进度的通知栏消息
参数说明
```
export type CreateNotificationProgressOptions = {
/**
* 通知标题
* @defaultValue 应用名称
*/
title ?: string | null
/**
* 通知内容
*/
content : string,
/**
* 进度
*/
progress : number,
/**
* 点击通知消息回调
* @defaultValue null
*/
onClick? : (() => void) | null
}
```
### uni.finishNotificationProgress(options: FinishNotificationProgressOptions) : void
完成时调用的API,比如下载完成后需要显示下载完成并隐藏进度时调用。
参数说明
```
export type FinishNotificationProgressOptions = {
/**
* 通知标题
* @defaultValue 应用名称
*/
title ?: string | null
/**
* 通知内容
*/
content : string,
/**
* 点击通知消息回调
*/
onClick : () => void
}
```
### cancelNotificationProgress() : void
取消通知消息显示
<?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.uniPush">
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<application>
<activity android:name="uts.sdk.modules.uniProgressNotification.TransparentActivity"
android:theme="@style/DCNotificationProgressTranslucentTheme" android:hardwareAccelerated="true"
android:screenOrientation="user" android:exported="true">
</activity>
</application>
</manifest>
\ No newline at end of file
import Activity from "android.app.Activity";
import Bundle from 'android.os.Bundle';
import Build from 'android.os.Build';
import View from 'android.view.View';
import Color from 'android.graphics.Color';
import WindowManager from 'android.view.WindowManager';
import { globalNotificationProgressFinishCallBack, globalNotificationProgressCallBack } from './index.uts';
import { ACTION_DOWNLOAD_FINISH, ACTION_DOWNLOAD_PROGRESS } from "./constant.uts"
export class TransparentActivity extends Activity {
constructor() {
super()
}
override onCreate(savedInstanceState : Bundle | null) {
super.onCreate(savedInstanceState)
this.fullScreen(this)
const action = this.getIntent().getAction()
if (action == ACTION_DOWNLOAD_FINISH) {
setTimeout(() => {
globalNotificationProgressFinishCallBack()
globalNotificationProgressFinishCallBack = () => { }
}, 100)
this.overridePendingTransition(0, 0)
}
if (action == ACTION_DOWNLOAD_PROGRESS) {
setTimeout(() => {
globalNotificationProgressCallBack?.()
globalNotificationProgressCallBack = () => { }
}, 100)
this.overridePendingTransition(0, 0)
}
setTimeout(() => {
this.finish()
}, 20)
}
@Suppress("DEPRECATION")
private fullScreen(activity : Activity) {
if (Build.VERSION.SDK_INT >= 19) {
if (Build.VERSION.SDK_INT >= 21) {
const window = activity.getWindow();
const decorView = window.getDecorView();
const option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
decorView.setSystemUiVisibility(option);
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(Color.TRANSPARENT);
} else {
const window = activity.getWindow();
const attributes = window.getAttributes();
const flagTranslucentStatus = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
attributes.flags |= flagTranslucentStatus;
window.setAttributes(attributes);
}
}
}
}
\ No newline at end of file
{
"minSdkVersion": "19"
}
\ No newline at end of file
export const ACTION_DOWNLOAD_FINISH = "ACTION_DOWNLOAD_FINISH"
export const ACTION_DOWNLOAD_PROGRESS = "ACTION_DOWNLOAD_PROGRESS"
\ No newline at end of file
import Build from 'android.os.Build';
import Context from 'android.content.Context';
import NotificationManager from 'android.app.NotificationManager';
import NotificationChannel from 'android.app.NotificationChannel';
import Notification from 'android.app.Notification';
import Intent from 'android.content.Intent';
import ComponentName from 'android.content.ComponentName';
import PendingIntent from 'android.app.PendingIntent';
import { CreateNotificationProgressOptions, FinishNotificationProgressOptions } from '../interface.uts';
import { ACTION_DOWNLOAD_FINISH, ACTION_DOWNLOAD_PROGRESS } from "./constant.uts"
export { TransparentActivity } from './TransparentActivity.uts';
const DOWNLOAD_PROGRESS_NOTIFICATION_ID : Int = 7890
const DC_DOWNLOAD_CHANNEL_ID = "下载文件"
const DC_DOWNLOAD_CHANNEL_NAME = "用于显示现在进度的渠道"
let notificationBuilder : Notification.Builder | null = null
let timeId = -1
let histroyProgress = 0
let isProgress = false
export let globalNotificationProgressCallBack : (() => void) | null = () => { }
export let globalNotificationProgressFinishCallBack = () => { }
export function createNotificationProgress(options : CreateNotificationProgressOptions) : void {
const { content, progress, onClick } = options
if (progress == 100) {
clearTimeout(timeId)
const context = UTSAndroid.getAppContext() as Context
realCreateNotificationProgress(options.title ?? getAppName(context), content, progress, onClick)
reset()
return
}
histroyProgress = progress
if (timeId != -1) {
return
}
const context = UTSAndroid.getAppContext() as Context
if (!isProgress) {
realCreateNotificationProgress(options.title ?? getAppName(context), content, histroyProgress, onClick)
isProgress = true
} else {
timeId = setTimeout(() => {
realCreateNotificationProgress(options.title ?? getAppName(context), content, histroyProgress, onClick)
timeId = -1
}, 1000)
}
}
export function cancelNotificationProgress() : void {
const context = UTSAndroid.getAppContext() as Context
const notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.cancel(DOWNLOAD_PROGRESS_NOTIFICATION_ID)
reset()
}
function realCreateNotificationProgress(title : string, content : string, progress : number, cb : (() => void) | null) : void {
globalNotificationProgressCallBack = cb
const context = UTSAndroid.getAppContext() as Context
const notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
createDownloadChannel(notificationManager)
const builder = createNotificationBuilder(context)
builder.setProgress(100, progress.toInt(), false)
builder.setContentTitle(title)
builder.setContentText(content)
builder.setContentIntent(createPendingIntent(context, ACTION_DOWNLOAD_PROGRESS));
notificationManager.notify(DOWNLOAD_PROGRESS_NOTIFICATION_ID, builder.build())
}
export function finishNotificationProgress(options : FinishNotificationProgressOptions) {
globalNotificationProgressFinishCallBack = options.onClick
const context = UTSAndroid.getAppContext() as Context
const notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
createDownloadChannel(notificationManager)
const builder = createNotificationBuilder(context)
builder.setProgress(0, 0, false)
builder.setContentTitle(options.title ?? getAppName(context))
builder.setContentText(options.content)
//小米rom setOngoing未false的时候,会被通知管理器归为不重要通知
// builder.setOngoing(false)
builder.setAutoCancel(true);
builder.setContentIntent(createPendingIntent(context, ACTION_DOWNLOAD_FINISH));
notificationManager.notify(DOWNLOAD_PROGRESS_NOTIFICATION_ID, builder.build())
reset()
}
function reset() {
isProgress = false
notificationBuilder = null
histroyProgress = 0
if (timeId != -1) {
clearTimeout(timeId)
timeId = -1
}
}
function createPendingIntent(context : Context, action : string) : PendingIntent {
const i = new Intent(action);
i.setComponent(new ComponentName(context.getPackageName(), "uts.sdk.modules.uniProgressNotification.TransparentActivity"));
let flags = PendingIntent.FLAG_ONE_SHOT;
if (Build.VERSION.SDK_INT >= 23) {
flags = PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_IMMUTABLE;
}
return PendingIntent.getActivity(context, DOWNLOAD_PROGRESS_NOTIFICATION_ID, i, flags);
}
function createDownloadChannel(notificationManager : NotificationManager) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
const channel = new NotificationChannel(
DC_DOWNLOAD_CHANNEL_ID,
DC_DOWNLOAD_CHANNEL_NAME,
NotificationManager.IMPORTANCE_LOW
)
notificationManager.createNotificationChannel(channel)
}
}
@Suppress("DEPRECATION")
function createNotificationBuilder(context : Context) : Notification.Builder {
if (notificationBuilder == null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
notificationBuilder = new Notification.Builder(context, DC_DOWNLOAD_CHANNEL_ID)
} else {
notificationBuilder = new Notification.Builder(context)
}
notificationBuilder!.setSmallIcon(context.getApplicationInfo().icon)
notificationBuilder!.setOngoing(true)
notificationBuilder!.setSound(null)
}
return notificationBuilder!
}
@Suppress("DEPRECATION")
function getAppName(context : Context) : string {
let appName = ""
try {
const packageManager = context.getPackageManager()
const applicationInfo = packageManager.getApplicationInfo(context.getPackageName(), 0)
appName = packageManager.getApplicationLabel(applicationInfo) as string
} catch (e : Exception) {
e.printStackTrace()
}
return appName
}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="DCNotificationProgressTranslucentTheme">
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:colorBackgroundCacheHint">@null</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowAnimationStyle">@android:style/Animation</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowContentOverlay">@null</item>
</style>
</resources>
\ No newline at end of file
{
"deploymentTarget": "9"
}
\ No newline at end of file
/**
* 引用 iOS 系统库,示例如下:
* import { UIDevice } from "UIKit";
* [可选实现,按需引入]
*/
/* 引入 interface.uts 文件中定义的变量 */
import { MyApiOptions, MyApiResult, MyApi, MyApiSync } from '../interface.uts';
/* 引入 unierror.uts 文件中定义的变量 */
import { MyApiFailImpl } from '../unierror';
/**
* 引入三方库
* [可选实现,按需引入]
*
* 在 iOS 平台引入三方库有以下两种方式:
* 1、通过引入三方库framework 或者.a 等方式,需要将 .framework 放到 ./Frameworks 目录下,将.a 放到 ./Libs 目录下。更多信息[详见](https://uniapp.dcloud.net.cn/plugin/uts-plugin.html#ios-平台原生配置)
* 2、通过 cocoaPods 方式引入,将要引入的 pod 信息配置到 config.json 文件下的 dependencies-pods 字段下。详细配置方式[详见](https://uniapp.dcloud.net.cn/plugin/uts-ios-cocoapods.html)
*
* 在通过上述任意方式依赖三方库后,使用时需要在文件中 import:
* 示例:import { LottieLoopMode } from 'Lottie'
*/
/**
* UTSiOS 为平台内置对象,不需要 import 可直接调用其API,[详见](https://uniapp.dcloud.net.cn/uts/utsios.html)
*/
/**
* 异步方法
*
* uni-app项目中(vue/nvue)调用示例:
* 1、引入方法声明 import { myApi } from "@/uni_modules/uts-api"
* 2、方法调用
* myApi({
* paramA: false,
* complete: (res) => {
* console.log(res)
* }
* });
*
*/
export const myApi : MyApi = function (options : MyApiOptions) {
if (options.paramA == true) {
// 返回数据
const res : MyApiResult = {
fieldA: 85,
fieldB: true,
fieldC: 'some message'
};
options.success?.(res);
options.complete?.(res);
} else {
// 返回错误
let failResult = new MyApiFailImpl(9010001);
options.fail?.(failResult)
options.complete?.(failResult)
}
}
/**
* 同步方法
*
* uni-app项目中(vue/nvue)调用示例:
* 1、引入方法声明 import { myApiSync } from "@/uni_modules/uts-api"
* 2、方法调用
* myApiSync(true);
*
*/
export const myApiSync : MyApiSync = function (paramA : boolean) : MyApiResult {
// 返回数据,根据插件功能获取实际的返回值
const res : MyApiResult = {
fieldA: 85,
fieldB: paramA,
fieldC: 'some message'
};
return res;
}
/**
* 更多插件开发的信息详见:https://uniapp.dcloud.net.cn/plugin/uts-plugin.html
*/
export type uni = {
/**
* createNotificationProgress()
* @description
* 创建通知栏下载进度消息
* @param {CreateNotificationProgressOptions}
* @return {void}
* @uniPlatform {
* "app": {
* "android": {
* "osVer": "4.4",
* "uniVer": "3.9+",
* "unixVer": "3.9+"
* },
* "ios": {
* "osVer": "x",
* "uniVer": "x",
* "unixVer": "x"
* }
* }
* }
* @example
```typescript
uni.createNotificationProgress({
title: "正在下载升级包",
content: "进度 50%",
progress: 50,
onClick:()=>{
console.log("正在下载");
}
}
```
*/
createNotificationProgress : (options : CreateNotificationProgressOptions) => void,
/**
* finishNotificationProgress()
* @description
* 通知栏显示下载完成,并且传入点击通知栏消息的回调。
* @param {FinishNotificationProgressOptions}
* @return {void}
* @uniPlatform {
* "app": {
* "android": {
* "osVer": "4.4",
* "uniVer": "3.9+",
* "unixVer": "3.9+"
* },
* "ios": {
* "osVer": "x",
* "uniVer": "x",
* "unixVer": "x"
* }
* }
* }
* @example
```typescript
uni.finishNotificationProgress({
title: "安装升级包",
content: "下载完成。",
onClick: () => {
uni.installApk({
filePath: e.tempFilePath,
complete(res) {
console.log(res);
}
})
}
}
```
*/
finishNotificationProgress : (options: FinishNotificationProgressOptions) => void,
/**
* cancelNotificationProgress()
* @description
* 取消通知消息显示
* @param {void}
* @return {void}
* @uniPlatform {
* "app": {
* "android": {
* "osVer": "4.4",
* "uniVer": "3.9+",
* "unixVer": "3.9+"
* },
* "ios": {
* "osVer": "x",
* "uniVer": "x",
* "unixVer": "x"
* }
* }
* }
* @example
```typescript
uni.cancelNotificationProgress()
```
*/
cancelNotificationProgress : () => void
}
export type CreateNotificationProgressOptions = {
/**
* 通知标题
* @defaultValue 应用名称
*/
title ?: string | null
/**
* 通知内容
*/
content : string,
/**
* 进度
*/
progress : number,
/**
* 点击通知消息回调
* @defaultValue null
*/
onClick? : (() => void) | null
}
export type FinishNotificationProgressOptions = {
/**
* 通知标题
* @defaultValue 应用名称
*/
title ?: string | null
/**
* 通知内容
*/
content : string,
/**
* 点击通知消息回调
*/
onClick : () => void
}
export type CreateNotificationProgress = (options : CreateNotificationProgressOptions) => void;
export type CancelNotificationProgress = () => void;
export type FinishNotificationProgress = (options: FinishNotificationProgressOptions) => void
\ No newline at end of file
{
"id": "uni-push",
"displayName": "uni-push",
"version": "1.0.0",
"description": "uni-push",
"keywords": [
"uni-push"
],
"repository": "",
"engines": {
"HBuilderX": "^3.6.8"
},
"dcloudext": {
"type": "uts",
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "",
"data": "",
"permissions": ""
},
"npmurl": ""
},
"uni_modules": {
"dependencies": [],
"uni-ext-api": {
"uni": {
"getPushClientId": {
"name": "getPushClientId",
"app": {
"js": false,
"kotlin": true,
"swift": false
}
},
"onPushMessage": {
"name": "onPushMessage",
"app": {
"js": false,
"kotlin": true,
"swift": false
}
},
"offPushMessage": {
"name": "offPushMessage",
"app": {
"js": false,
"kotlin": true,
"swift": false
}
},
"getChannelManager": {
"name": "getChannelManager",
"app": {
"js": false,
"kotlin": true,
"swift": false
}
},
"createPushMessage": {
"name": "createPushMessage",
"app": {
"js": false,
"kotlin": true,
"swift": false
}
}
}
},
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "u",
"aliyun": "u"
},
"client": {
"Vue": {
"vue2": "u",
"vue3": "u"
},
"App": {
"app-android": "u",
"app-ios": "u"
},
"H5-mobile": {
"Safari": "u",
"Android Browser": "u",
"微信浏览器(Android)": "u",
"QQ浏览器(Android)": "u"
},
"H5-pc": {
"Chrome": "u",
"IE": "u",
"Edge": "u",
"Firefox": "u",
"Safari": "u"
},
"小程序": {
"微信": "u",
"阿里": "u",
"百度": "u",
"字节跳动": "u",
"QQ": "u",
"钉钉": "u",
"快手": "u",
"飞书": "u",
"京东": "u"
},
"快应用": {
"华为": "u",
"联盟": "u"
}
}
}
}
}
\ No newline at end of file
# uni-push
`uni-push` 工程,是基于 DCloud-UTS 架构之上的封装个推消息推送 `SDK` 的插件工程,使用此模块可轻松实现服务端向客户端推送通知和透传消息的功能。
### 插件使用说明
#### 导入插件
```uts
import * as GTPlugin from "../../uni_modules/uni-push"
```
#### 初始化
```typescript
//初始化个推推送
GTPlugin.initPush();
```
#### 推送消息事件
> 添加透传消息回调,对应的GTPlugin.offPushMessage()可移除对应监听callback(传入null,可移除所有监听callback)
```typescript
GTPlugin.onPushMessage((res) => {
console.log("onPushMessage => " + JSON.stringify(res))
})
```
| 名称 | 类型 | 描述 |
| ---- | ------------- | ----------------------------------------------------------- |
| type | String | 事件类型,"click"-从系统推送服务点击消息启动应用事件;"receive"-应用从推送服务器接收到推送消息事件。 |
| data | String、Object | 消息内容 |
#### 日志
开发阶段,需要使用到日志辅助。
```typescript
//设置日志回调,可以在控制台看到[GT-PUSH]的日志
GTPlugin.setDebugLogger(function(res) {
console.log(res)
});
```
当插件正常初始化会出现以下日志:
```uts
16:47:53.254 [GT-PUSH] [LogController] Sdk version = 3.3.0.0 at pages/index/index.vue:25
16:47:54.052 [GT-PUSH] [ServiceManager] ServiceManager start from initialize... at pages/index/index.vue:25
16:47:54.073 [GT-PUSH] PushCore started at pages/index/index.vue:25
16:47:54.274 [GT-PUSH] onHandleIntent() = get sdk service pid at pages/index/index.vue:25
16:47:54.292 [GT-PUSH] onHandleIntent() areNotificationsEnabled at pages/index/index.vue:25
16:47:54.353 [GT-PUSH] [LoginInteractor] Start login appid = nU*******wzf at pages/index/index.vue:25
16:47:54.571 收到 cid onReceiveClientId : 3061f********ce7578eb24 at pages/index/index.vue:29
16:47:54.592 [GT-PUSH] onHandleIntent() = received client id at pages/index/index.vue:25
16:47:54.593 [GT-PUSH] [LoginResult] Login successed with cid = 3061f********ce7578eb24 at pages/index/index.vue:25
```
#### 推送相关动作
> 设置推送相关动作回调,更多可查看`app-android/index.uts`下面的 `UserPushAction`类
```typescript
GTPlugin.setPushAction({
onReceiveClientId: function(cid) {
console.log("收到 cid onReceiveClientId : " + cid)
}
});
```
#### 唯一的推送标识
获取客户端唯一的推送标识
```typescript
GTPlugin.getPushClientId({
success: (res) => {
console.log("getPushClientId success => " + JSON.stringify(res));
},
fail: (res) => {
console.log("getPushClientId fail => " + JSON.stringify(res));
},
complete: (res) => {
console.log("getPushClientId complete => " + JSON.stringify(res));
}
});
```
**OBJECT 参数说明**
| 参数名 | 类型 | 必填 | 说明 |
| -------- | -------- | --- | ------------------------ |
| success | Function | 是 | 接口调用的回调函数,详见返回参数说明 |
| fail | Function | 否 | 接口调用失败的回调函数 |
| complete | Function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
**success 返回参数说明**
| 参数 | 类型 | 说明 |
| ------ | ------ | ---------------------------------------- |
| cid | String | 个推客户端推送id,对应uni-id-device表的push_clientid |
| errMsg | String | 错误描述 |
**fail 返回参数说明**
| 参数 | 类型 | 说明 |
| ------ | ------ | ---- |
| errMsg | String | 错误描述 |
### APP_ID申请
可登录[个推官网](https://dev.getui.com/)注册申请应用,获取APP相关信息。
### 多厂商
多厂商渠道可以参考[[厂商应用开通指南-个推文档中心](https://docs.getui.com/getui/mobile/vendor/vendor_open/)[厂商 SDK 集成指南-个推文档中心](https://docs.getui.com/getui/mobile/vendor/androidstudio/)
> 注意:华为厂商需要把`agconnect-services.json` 放到${工程根目录}/nativeResources/android/ 目录下
### 开发文档
[个推推送SDK](https://docs.getui.com/getui/start/accessGuide/)
[多厂商接入](https://docs.getui.com/getui/mobile/vendor/vendor_open/)
### 注意事项
`AndroidManifest.xml`中,必须声明插件`flag`
```xml
<!-- 标识dcloud -->
<meta-data android:name="GETUI_PLUGIN_FLAG" android:value="dcloud"/>
```
<?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.uniPush">
<application>
<activity android:name="io.dcloud.uniapp.UniAppActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:host="io.dcloud.unipush" android:path="/" android:scheme="unipush" />
</intent-filter>
</activity>
<!-- 如果插件中注册组件时, 包名应为: `uts.sdk.modules.uniPush.PushActionService` , 但由于此插件是内部插件, 所以包名改为: `uts.sdk.modules.DCloudUniPush.PushActionService` -->
<service android:name="uts.sdk.modules.DCloudUniPush.PushActionService" android:exported="false" />
<meta-data android:name="GETUI_APPID" android:value="${GETUI_APPID}" />
<meta-data android:name="MIPUSH_APPID" android:value="XM_${MIPUSH_APPID}" />
<meta-data android:name="MIPUSH_APPKEY" android:value="XM_${MIPUSH_APPKEY}" />
<meta-data android:name="MEIZUPUSH_APPID" android:value="MZ_${MEIZUPUSH_APPID}" />
<meta-data android:name="MEIZUPUSH_APPKEY" android:value="MZ_${MEIZUPUSH_APPKEY}" />
<meta-data android:name="OPPOPUSH_APPKEY" android:value="OP_${OPPOPUSH_APPKEY}" />
<meta-data android:name="OPPOPUSH_APPSECRET" android:value="OP_${OPPOPUSH_APPSECRET}" />
<meta-data android:name="com.huawei.hms.client.appid" android:value="${com.huawei.hms.client.appid}" />
<meta-data android:name="com.vivo.push.app_id" android:value="${com.vivo.push.app_id}" />
<meta-data android:name="com.vivo.push.api_key" android:value="${com.vivo.push.api_key}" />
<meta-data android:name="dcloud_unipush_auto_notification" android:value="${dcloud_unipush_auto_notification}" />
</application>
</manifest>
\ No newline at end of file
{
"parameters": {
"appid": {
"placeholder": "GETUI_APPID"
},
"mipush_appid": {
"placeholder": "MIPUSH_APPID"
},
"mipush_appkey": {
"placeholder": "MIPUSH_APPKEY"
},
"meizupush_appid": {
"placeholder": "MEIZUPUSH_APPID"
},
"meizupush_appkey": {
"placeholder": "MEIZUPUSH_APPKEY"
},
"oppopush_appkey": {
"placeholder": "OPPOPUSH_APPKEY"
},
"oppopush_appsecret": {
"placeholder": "OPPOPUSH_APPSECRET"
},
"huaweipush_appid": {
"placeholder": "com.huawei.hms.client.appid"
},
"vivopush_appid": {
"placeholder": "com.vivo.push.app_id"
},
"vivopush_appkey": {
"placeholder": "com.vivo.push.api_key"
},
"dcloud_unipush_auto_notification": {
"placeholder": "dcloud_unipush_auto_notification"
}
},
"files": [{
"source": "push_unipush_huaweipush_agconnect-services.json",
"target": "agconnect-services.json",
"des": "HMS配置文件"
}]
}
\ No newline at end of file
import Context from "android.content.Context";
import GTPlugin from "com.getui.sdk.GTPlugin";
import IPushAction from "com.getui.sdk.IPushAction";
import GTCmdMessage from "com.igexin.sdk.message.GTCmdMessage";
import GTNotificationMessage from "com.igexin.sdk.message.GTNotificationMessage";
import GTTransmitMessage from "com.igexin.sdk.message.GTTransmitMessage";
import IUserLoggerInterface from "com.igexin.sdk.IUserLoggerInterface";
export function gtInit(context : Context) : void {
GTPlugin.initialize(context);
}
export function getClientId(context : Context) : string {
return GTPlugin.getClientId(context);
}
export function setPushAction(action : UserPushAction) : void {
GTPlugin.setPushAction(action);
}
export type GTPushActionOptions = {
onReceiveServicePid ?: (res : number) => void
/**
* 接收clientId(cid)
*/
onReceiveClientId ?: (res : string) => void
/**
* 此方法用于接收和处理透传消息。透传消息个推只传递数据,不做任何处理,客户端接收到透传消息后需要自己去做后续动作处理,如通知栏展示、弹框等。
* 如果开发者在客户端将透传消息创建了通知栏展示,建议将展示和点击回执上报给个推。
*/
onReceiveMessageData ?: (res : string) => void
/**
* cid 离线上线通知
*/
onReceiveOnlineState ?: (res : boolean) => void
/**
* 各种事件处理回执
*/
onReceiveCommandResult ?: (res : GTCmdMessage) => void
/**
* 通知点击,只有个推通道下发的通知会回调此方法
*/
onNotificationMessageClicked ?: (res : string) => void
/**
* 通知到达,只有个推通道下发的通知会回调此方法
*/
onNotificationMessageArrived ?: (res : GTNotificationMessage) => void
}
export class UserPushAction implements IPushAction {
constructor(
private options : GTPushActionOptions) {
}
override onReceiveServicePid(ctx : Context, pid : Int) {
this.options.onReceiveServicePid?.(pid)
}
/**
* 接收clientId(cid)
*/
override onReceiveClientId(ctx : Context, cid : string) {
this.options.onReceiveClientId?.(cid)
}
/**
* 此方法用于接收和处理透传消息。透传消息个推只传递数据,不做任何处理,客户端接收到透传消息后需要自己去做后续动作处理,如通知栏展示、弹框等。
* 如果开发者在客户端将透传消息创建了通知栏展示,建议将展示和点击回执上报给个推。
*
* class GTTransmitMessage {
* private String taskId;
* private String messageId;
* private String payloadId;
* private byte[] payload;
* }
*/
override onReceiveMessageData(ctx : Context, message : GTTransmitMessage) {
this.options.onReceiveMessageData?.(new String(message.getPayload()))
}
/**
* cid 离线/上线通知
*/
override onReceiveOnlineState(ctx : Context, state : boolean) {
this.options.onReceiveOnlineState?.(state)
}
/**
* 各种事件处理回执
*/
override onReceiveCommandResult(ctx : Context, message : GTCmdMessage) {
this.options.onReceiveCommandResult?.(message)
}
/**
* 通知点击,只有个推通道下发的通知会回调此方法
*/
override onNotificationMessageClicked(ctx : Context, message : GTNotificationMessage) {
const params = {
"title": message.getTitle(),
"content": message.getContent()
};
this.options.onNotificationMessageClicked?.(JSON.stringify(params))
}
/**
* 通知到达,只有个推通道下发的通知会回调此方法
*/
override onNotificationMessageArrived(ctx : Context, message : GTNotificationMessage) {
this.options.onNotificationMessageArrived?.(message)
}
}
class UserLoggerInterface implements IUserLoggerInterface {
constructor(private callback : (log : string) => void) {
}
override log(s : string) {
this.callback?.(s)
}
}
/**
* 个推推送sdk调试日志信息
* setDebugLogger 接口仅限调试的时候使用,切勿发布到线上版本,重复调用仅以第一次为准。
*/
export function setDebugLogger(callback : (log : string) => void) {
const ctx = UTSAndroid.getAppContext();
if (ctx != null) {
GTPlugin.setDebugLogger(ctx, new UserLoggerInterface(callback))
}
}
\ No newline at end of file
import { GetPushClientIdOptions, GetPushClientIdSuccess, GetPushClientIdFail, OnPushMessageCallback, OnPushMessageCallbackResult, OnPushMessageType, CreatePushMessageOptions, ChannelManager } from '../interface.uts'
import { gtInit, GTPushActionOptions, UserPushAction, setPushAction } from './gt-sdk/GTPush.uts'
import Context from 'android.content.Context';
import { PushMessage } from './push/PushMessage.uts';
import PackageManager from 'android.content.pm.PackageManager';
import ApplicationInfo from 'android.content.pm.ApplicationInfo';
import Activity from 'android.app.Activity';
import TextUtils from 'android.text.TextUtils';
import { PushState } from './push/PushState.uts';
import { PushManager } from './push/PushManager.uts';
import { StringUtil } from './push/utils/StringUtil.uts';
import SharedPreferences from 'android.content.SharedPreferences';
import Handler from 'android.os.Handler';
import { PushChannelManager } from './push/PushChannelManager.uts';
import Bundle from 'android.os.Bundle';
import Intent from 'android.content.Intent';
import Uri from 'android.net.Uri';
import { globalPushMessageCallbacks, sendEvent } from './push/PushManager.uts'
export { PushActionService } from './push/PushActionService.uts';
const SP_NAME = "clientid_unipush";
const SP_KEY_CLIENT_ID = "clientid";
let gtCallBack : UserPushAction | null = null;
let gtPushInitialize = false
/**
* 个推推送sdk初始化
*/
function initPush() {
const ctx = UTSAndroid.getAppContext();
if (ctx != null && !gtPushInitialize) {
gtPushInitialize = true;
gtInit(ctx);
setPushAction(getGTCallBack());
}
}
/**
* 获取客户端唯一的推送标识(注意:这是一个异步的方法)
*/
export function getPushClientId(options : GetPushClientIdOptions) {
initPush()
const ctx = UTSAndroid.getAppContext() as Context;
const sp = ctx.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE) as SharedPreferences;
const clientId = sp.getString(SP_KEY_CLIENT_ID, "")
if (TextUtils.isEmpty(clientId)) {
const handler = new Handler()
const changeListener = new (class implements SharedPreferences.OnSharedPreferenceChangeListener {
override onSharedPreferenceChanged(sharedPreferences : SharedPreferences, key : string) : void {
if (key != SP_KEY_CLIENT_ID) {
return
}
handler.removeCallbacksAndMessages(null)
sharedPreferences.unregisterOnSharedPreferenceChangeListener(this)
const cid = sharedPreferences.getString(SP_KEY_CLIENT_ID, "")
const res : GetPushClientIdSuccess = { errMsg: "success", cid: cid!! }
options.success?.(res)
options.complete?.(res)
}
})
sp.registerOnSharedPreferenceChangeListener(changeListener)
const runnable = new (class implements Runnable {
override run() {
const clientId = sp.getString(SP_KEY_CLIENT_ID, "")
if (!TextUtils.isEmpty(clientId)) {
const res : GetPushClientIdSuccess = { errMsg: "success", cid: clientId!! }
options.success?.(res)
options.complete?.(res)
} else {
const res : GetPushClientIdFail = {
errSubject: "uni-push",
errCode: -1,
errMsg: "failed,check appkey or appid",
}
options.fail?.(res)
options.complete?.(res)
}
}
})
handler.postDelayed(runnable, 15000)
} else {
const res : GetPushClientIdSuccess = { errMsg: "success", cid: clientId!! }
options.success?.(res)
options.complete?.(res)
}
}
/**
* 增加监听推送消息事件(应用在线的时候没有通知栏消息,全部是透传。), 注意: 使用时,开发者需要注册写到第一个activity的周期内 , 即首页.
*/
export function onPushMessage(callback : OnPushMessageCallback | null) {
initPush()
if (callback == null) {
return;
}
if (globalPushMessageCallbacks.indexOf(callback) == -1) {
globalPushMessageCallbacks.push(callback)
}
processOfflineMessage()
// 处理没有注册监听时,已经接到的消息,此时从缓存里取
PushManager.getInstance().comsumeMessages("click", (msgs : PushMessage[]) => {
msgs.forEach((msg) => {
sendEvent("click", msg)
})
})
PushManager.getInstance().comsumeMessages("receive", (msgs : PushMessage[]) => {
msgs.forEach((msg) => {
sendEvent("receive", msg)
})
})
}
/**
* 移除推送消息监听事件(没有传入参数,则移除App级别的所有事件监听器。)
*/
export function offPushMessage(callback : OnPushMessageCallback | null) {
if (callback == null) {
const len = globalPushMessageCallbacks.length;
globalPushMessageCallbacks.splice(0, len)
return;
}
let index = globalPushMessageCallbacks.indexOf(callback)
if (index == -1) {
return;
}
globalPushMessageCallbacks.splice(index, 1)
}
export function getChannelManager() : ChannelManager {
return PushChannelManager.getInstance()
}
export function createPushMessage(options : CreatePushMessageOptions) : void {
const context = UTSAndroid.getAppContext() as Context
const appId = UTSAndroid.getAppId()
const pushMessage = new PushMessage(JSON.stringify(options), getApplicationName(), false)
const min = 0
if (pushMessage.mDelay == min.toLong()) {
PushManager.getInstance().addPushMessage(appId, pushMessage)
PushManager.getInstance().createNotification(context, pushMessage)
} else {
new Handler().postDelayed(new (class implements Runnable {
override run() {
PushManager.getInstance().addPushMessage(appId, pushMessage)
PushManager.getInstance().createNotification(context, pushMessage)
}
}), pushMessage.mDelay * 1000)
}
}
function getGTCallBack() : UserPushAction {
if (gtCallBack == null) {
const options = {
onReceiveClientId(cid : string) {
const context = UTSAndroid.getAppContext() as Context;
const sp = context.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);
const editor = sp.edit();
editor.putString(SP_KEY_CLIENT_ID, cid);
editor.commit();
},
onNotificationMessageClicked(res : string) {
const pushMessage = new PushMessage(res, getApplicationName(), false)
if (!sendEvent("click", pushMessage)) {
PushManager.getInstance().addNeedExecClickMessage(pushMessage)
}
},
onReceiveMessageData(res : string) {
if (!TextUtils.isEmpty(res)) {
let isUniPush2 = false
const jsonObject = JSON.parseObject(res)
const unipushVersionStr = jsonObject?.getString("unipush_version")
if (!TextUtils.isEmpty(unipushVersionStr)) {
const unipushVersion = parseFloat(unipushVersionStr!!)
if (unipushVersion == 2.0) {
isUniPush2 = true;
}
}
if (isUniPush2) {
processForUniPush2(res);
} else {
processForUniPush(res);
}
}
},
} as GTPushActionOptions;
gtCallBack = new UserPushAction(options);
}
return gtCallBack!!;
}
/**
* 处理离线消息
*/
function processOfflineMessage() {
const activity = UTSAndroid.getUniActivity() as Activity
const intent = activity.getIntent()
// const testStr = "intent://io.dcloud.unipush/?#Intent;scheme=unipush;launchFlags=0x4000000;package=uni.UNI8CD4C4C;component=uni.UNI8CD4C4C/io.dcloud.uniapp.UniAppActivity;S.UP-OL-SU=true;S.unipush_version=2.0;S.payload={\"cccccforceNotification\":\"xxx\",\"path\":\"XXX\"};S.title=xxx;S.content=xxx;S.unipush_data={\"forceNotification\":\"xxx\",\"path\":\"XXX\"};end"
// const intent = Intent.parseUri(testStr , 0)
if (intent.hasExtra("UP-OL-SU")) {
let isUniPush2 = false;
const unipushVersionStr = intent.getStringExtra("unipush_version");
if (!TextUtils.isEmpty(unipushVersionStr)) {
const unipushVersion = parseFloat(unipushVersionStr!!)
if (unipushVersion == 2.0) {
isUniPush2 = true;
}
}
const params = {}
if (isUniPush2) {
try {
params["title"] = intent.getStringExtra("title")
params["content"] = intent.getStringExtra("content")
params["unipush_version"] = intent.getStringExtra("unipush_version")
const channelId = intent.getStringExtra("channelId");
const category = intent.getStringExtra("category");
if (!TextUtils.isEmpty(channelId)) {
params["channelId"] = channelId
}
if (!TextUtils.isEmpty(category)) {
params["category"] = category
}
let payload = intent.getStringExtra("payload");
const payloadJsonObject = JSON.parseObject(payload ?? "")
if (payloadJsonObject == null) {
if (payload != null) {
//如果后端传的不是json,而是纯字符串,就需要单独处理,去掉多余的引号,并且枚举一下类型.
//双引号套双引号,就说明是传的字符串.
if (payload.startsWith("\"")) {
payload = StringUtil.trimString(payload, '"');
params["payload"] = payload
} else {
const payloadInt = StringUtil.getInt(payload);
const payloadDouble = StringUtil.getDouble(payload);
if (payloadInt != null) {
params["payload"] = payloadInt
} else if (payloadDouble != null) {
params["payload"] = payloadDouble
} else if (payload == "true" || payload == "false") {
params["payload"] = payload.toBoolean()
} else {
params["payload"] = payload
}
}
}
} else {
params["payload"] = payloadJsonObject
}
const unipush_data = intent.getStringExtra("unipush_data");
const unipushDataJsonObject = JSON.parseObject(unipush_data ?? "");
if (unipushDataJsonObject != null) {
unipushDataJsonObject.toMap().forEach((value, key) => {
params[key] = value
})
}
intent.removeExtra("UP-OL-SU");
intent.removeExtra("title");
intent.removeExtra("content");
intent.removeExtra("payload");
intent.removeExtra("unipush_version");
intent.removeExtra("unipush_data");
intent.removeExtra("channelId");
intent.removeExtra("category");
const data = JSON.stringify(params)
const pushMessage = new PushMessage(data, getApplicationName(), true);
if (!sendEvent("click", pushMessage)) {
PushManager.getInstance().addNeedExecClickMessage(pushMessage)
}
} catch (e : Exception) {
e.printStackTrace();
}
} else {
try {
params["title"] = intent.getStringExtra("title")
params["content"] = intent.getStringExtra("content")
params["payload"] = intent.getStringExtra("payload")
const channelId = intent.getStringExtra("channelId");
const category = intent.getStringExtra("category");
if (!TextUtils.isEmpty(channelId)) {
params["channelId"] = channelId
}
if (!TextUtils.isEmpty(category)) {
params["category"] = category
}
intent.removeExtra("UP-OL-SU");
intent.removeExtra("title");
intent.removeExtra("content");
intent.removeExtra("payload");
intent.removeExtra("channelId");
intent.removeExtra("category");
const data = JSON.stringify(params)
const pushMessage = new PushMessage(data, getApplicationName(), true);
if (!sendEvent("click", pushMessage)) {
PushManager.getInstance().addNeedExecClickMessage(pushMessage)
}
} catch (e : Exception) {
e.printStackTrace();
}
}
}
}
function processForUniPush(data : string) : void {
const context = UTSAndroid.getAppContext() as Context
const pushMessage = new PushMessage(data, getApplicationName(), false)
const needPush = PushState.getAutoNotification()
if (needPush && pushMessage.getNeedCreateNotification()) {
PushManager.getInstance().createNotification(context, pushMessage)
} else if (!sendEvent("receive", pushMessage)) {
PushManager.getInstance().addNeedExecReceiveMessage(pushMessage);
}
PushManager.getInstance().addPushMessage(UTSAndroid.getAppId(), pushMessage);
}
function processForUniPush2(data : string) : void {
const context = UTSAndroid.getAppContext() as Context
const jsonObject = JSON.parseObject(data)
if (jsonObject != null) {
const forceNotification = jsonObject.getBoolean("force_notification")
const pushMessage = new PushMessage(data, getApplicationName(), true)
if (forceNotification != null && forceNotification) {
PushManager.getInstance().createNotification(context, pushMessage)
} else if (!sendEvent("receive", pushMessage)) {
PushManager.getInstance().addNeedExecReceiveMessage(pushMessage);
}
PushManager.getInstance().addPushMessage(UTSAndroid.getAppId(), pushMessage);
}
}
function getApplicationName() : string {
let packageManager : PackageManager | null = null
let applicationInfo : ApplicationInfo | null = null
const context = UTSAndroid.getAppContext() as Context;
try {
packageManager = context.getApplicationContext().getPackageManager()
applicationInfo = packageManager.getApplicationInfo(context.getPackageName(), 0)
} catch (_ : Exception) {
}
if (applicationInfo == null) {
return ""
}
return packageManager?.getApplicationLabel(applicationInfo).toString() ?? ""
}
\ No newline at end of file
import Service from 'android.app.Service';
import Intent from 'android.content.Intent';
import IBinder from 'android.os.IBinder';
import { PushManager } from './PushManager.uts';
export class PushActionService extends Service {
constructor(){
super();
}
override onBind(intent : Intent) : IBinder | null {
return null
}
override onStartCommand(intent : Intent | null, flag : Int, startId : Int) : Int {
if (intent != null) {
PushManager.getInstance().processAction(this.getBaseContext(), intent)
}
return super.onStartCommand(intent, flag, startId)
}
}
\ No newline at end of file
import { ChannelManager, SetPushChannelOptions } from "../../interface.uts";
import Context from 'android.content.Context';
import Build from 'android.os.Build';
import NotificationManager from 'android.app.NotificationManager';
import NotificationChannelGroup from 'android.app.NotificationChannelGroup';
import NotificationChannel from 'android.app.NotificationChannel';
import TextUtils from 'android.text.TextUtils';
import ContentResolver from 'android.content.ContentResolver';
import Uri from 'android.net.Uri';
import RingtoneManager from 'android.media.RingtoneManager';
export class PushChannelManager implements ChannelManager {
static LOCAL_PUSH_CHANNEL_ID = "DcloudChannelID";
static LOCAL_PUSH_GROUP_ID = "DcloudGroupID";
private static INSTANCE : PushChannelManager | null = null
static getInstance() : PushChannelManager {
if (this.INSTANCE == null) {
this.INSTANCE = new PushChannelManager()
}
return this.INSTANCE!!
}
createDefaultChannel(context : Context) {
if (Build.VERSION.SDK_INT >= 26) {
const notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
const pChannelId = PushChannelManager.LOCAL_PUSH_CHANNEL_ID
const pChannelName = context.getResources().getString(R.string.dcloud_feature_aps_notification_channel)
if (notificationManager.getNotificationChannel(pChannelId) == null) {
notificationManager.createNotificationChannelGroup(new NotificationChannelGroup(PushChannelManager.LOCAL_PUSH_GROUP_ID, context.getResources().getString(R.string.dcloud_feature_aps_notification_group)))
const channel = new NotificationChannel(pChannelId, pChannelName, NotificationManager.IMPORTANCE_DEFAULT)
channel.enableLights(true)
channel.setShowBadge(true)
notificationManager.createNotificationChannel(channel)
}
}
}
/**
* 设置推送渠道
*/
setPushChannel(options : SetPushChannelOptions) : void {
if (Build.VERSION.SDK_INT >= 26) {
const context = UTSAndroid.getAppContext() as Context
const notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager;
if (notificationManager.getNotificationChannel(options.channelId) == null) {
const notificationChannel = new NotificationChannel(options.channelId, options.channelDesc, NotificationManager.IMPORTANCE_DEFAULT);
notificationChannel.setShowBadge(true);
let sound = 0;
if (!TextUtils.isEmpty(options.soundName)) {
const packName = context.getApplicationInfo().packageName
sound = context.getResources().getIdentifier(options.soundName!!, "raw", packName)
}
let uriStr = "";
if (sound != 0) {
uriStr = ContentResolver.SCHEME_ANDROID_RESOURCE + "://" + context.getPackageName() + "/raw/" + sound;
}
if (!TextUtils.isEmpty(uriStr)) {
notificationChannel.setSound(Uri.parse(uriStr), null);
} else {
const uri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);//默认铃音
notificationChannel.setSound(uri, null);
}
if (options.importance != null) {
notificationChannel.setImportance(options.importance!!.toInt());
}
if (options.lockscreenVisibility != null) {
notificationChannel.setLockscreenVisibility(options.lockscreenVisibility!!.toInt());
}
notificationChannel.enableLights(options.enableLights ?? false);
notificationChannel.enableVibration(options.enableVibration ?? false);
notificationManager.createNotificationChannel(notificationChannel);
}
}
}
/**
* 获取当前应用注册的所有的通知渠道。
*/
getAllChannels() : string[] {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
const context = UTSAndroid.getAppContext() as Context
const nm = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
const channels : string[] = []
const list = nm.getNotificationChannels()
for (let i:Int = 0; i < list.size; i++) {
channels.push(list.get(i).toString())
}
return channels
}else{
return [] as string[]
}
}
}
\ No newline at end of file
import Context from 'android.content.Context';
import Intent from 'android.content.Intent';
import { PushChannelManager } from './PushChannelManager.uts';
import { PushMessage } from './PushMessage.uts';
import NotificationManager from 'android.app.NotificationManager';
import ComponentName from 'android.content.ComponentName';
import PendingIntent from 'android.app.PendingIntent';
import Build from 'android.os.Build';
import TextUtils from 'android.text.TextUtils';
import Notification from 'android.app.Notification';
import Bitmap from 'android.graphics.Bitmap';
import BitmapFactory from 'android.graphics.BitmapFactory';
import File from 'java.io.File';
import { OnPushMessageCallback, OnPushMessageType, OnPushMessageCallbackResult } from '../../interface.uts'
export const globalPushMessageCallbacks : OnPushMessageCallback[] = []
export function sendEvent(type : OnPushMessageType, pushMessage : PushMessage) : boolean {
const data = pushMessage.getJsonObject()
const result : OnPushMessageCallbackResult = {
type: type,
data: data
}
if (globalPushMessageCallbacks.length == 0) {
return false
} else {
globalPushMessageCallbacks.forEach((cb : OnPushMessageCallback) => {
cb(result)
})
return true
}
}
export class PushManager {
private static INSTANCE : PushManager | null = null
private ACTION_TYPE_CREATE = "ACTION_TYPE_CREATE"
private ACTION_TYPE_REMOVE = "ACTION_TYPE_REMOVE"
private ACTION_TYPE_CLEAR = "ACTION_TYPE_CLEAR"
private ACTION_TYPE_CLICK = "ACTION_TYPE_CLICK"
private mAppMessages : Map<string, Array<PushMessage>> = new Map()
private mNeedExecClickMessages : PushMessage[] = []
private mNeedExecReceiveMessages : PushMessage[] = []
static getInstance() : PushManager {
if (this.INSTANCE == null) {
this.INSTANCE = new PushManager()
}
return this.INSTANCE!!
}
createNotification(context : Context, message : PushMessage) {
PushChannelManager.getInstance().createDefaultChannel(context)
const intent = new Intent(this.ACTION_TYPE_CREATE)
intent.putExtras(message.toBundle())
this.processAction(context, intent)
}
addPushMessage(pAppid : string, pMsg : PushMessage) {
let _arr = this.mAppMessages.get(pAppid);
if (_arr == null) {
_arr = new Array<PushMessage>();
this.mAppMessages.set(pAppid, _arr);
}
_arr.push(pMsg);
}
addNeedExecClickMessage(pushMessage : PushMessage) {
if (this.mNeedExecClickMessages.length > 0) {
this.mNeedExecClickMessages = []
}
this.mNeedExecClickMessages.push(pushMessage)
}
addNeedExecReceiveMessage(pushMessage : PushMessage) {
this.mNeedExecReceiveMessages.push(pushMessage)
}
removePushMessage(pAppid : String, pPushMsg : PushMessage) {
const _arr = this.mAppMessages.get(pAppid);
if (_arr != null && _arr.indexOf(pPushMsg) > 0) {
_arr.splice(_arr.indexOf(pPushMsg), 1);
}
}
/**
* 消费缓存的消息
*/
comsumeMessages(type : string, cb : (msgs : PushMessage[]) => void) {
if (type == "click") {
cb(this.mNeedExecClickMessages)
this.mNeedExecClickMessages.splice(0)
} else if (type == "receive") {
cb(this.mNeedExecReceiveMessages)
this.mNeedExecReceiveMessages.splice(0)
}
}
processAction(context : Context, intent : Intent) {
const notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
const action = intent.getAction()
switch (action) {
case this.ACTION_TYPE_CREATE:
{
const title = intent.getStringExtra("title");
const message = intent.getStringExtra("content");
const nId = intent.getIntExtra("nId", 0);
const when = intent.getLongExtra("when", 0);
const appid = intent.getStringExtra("appid");
const icon = intent.getStringExtra("icon");
const sound = intent.getStringExtra("sound");
const category = intent.getStringExtra("category");
let channelId = intent.getStringExtra("channelId");
const i = new Intent(this.ACTION_TYPE_CLICK);
i.setComponent(new ComponentName(context.getPackageName(), "uts.sdk.modules.DCloudUniPush.PushActionService"));
i.putExtras(intent.getExtras()!!);
let flags = PendingIntent.FLAG_ONE_SHOT;
if (Build.VERSION.SDK_INT >= 23) {
flags = PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_IMMUTABLE;
}
const contentIntent = PendingIntent.getService(context, nId, i, flags);
let builder : Notification.Builder | null = null;
if (Build.VERSION.SDK_INT >= 26) {
if (TextUtils.isEmpty(channelId)) {
channelId = PushChannelManager.LOCAL_PUSH_CHANNEL_ID;
}
builder = new Notification.Builder(context, channelId);
} else {
builder = new Notification.Builder(context);
}
let bitmap : Bitmap | null = null;
try {
if (!TextUtils.isEmpty(icon) && this.fileIsExist(icon!!)) {
bitmap = BitmapFactory.decodeFile(icon!!);
}
} catch (e : Exception) {
e.printStackTrace();
}
if (bitmap != null) {
builder.setLargeIcon(bitmap);
}
const id_small = context.getResources().getIdentifier("push_small", "drawable", context.getPackageName())
if (id_small <= 0) {
builder.setSmallIcon(context.getApplicationInfo().icon); //设置图标
} else {
builder.setSmallIcon(id_small); //设置图标
}
const id = context.getResources().getIdentifier("push", "drawable", context.getPackageName())
if (bitmap == null) {
let largeBitmap : Bitmap | null = null;
if (id <= 0) {
largeBitmap = BitmapFactory.decodeResource(context.getResources(), context.getApplicationInfo().icon);
} else {
largeBitmap = BitmapFactory.decodeResource(context.getResources(), id);
}
if (null != largeBitmap) {
builder.setLargeIcon(largeBitmap);
}
}
builder.setContentTitle(title); //设置标题
builder.setContentText(message); //消息内容
if (Build.VERSION.SDK_INT >= 24) {
builder.setShowWhen(true);
}
builder.setWhen(when); //发送时间
// 添加声音提示
if ("system" == sound) {
builder.setDefaults(Notification.DEFAULT_SOUND); //设置默认的提示音,振动方式,灯光
}
builder.setAutoCancel(true);//打开程序后图标消失
builder.setContentIntent(contentIntent);
builder.setCategory(category);
const notification = builder.build();
try {
notificationManager.notify(nId, notification);
} catch (e : Exception) {
e.printStackTrace();
}
}
break;
case this.ACTION_TYPE_REMOVE:
{
const _id = intent.getIntExtra("id", 0);
if (_id != null) {
notificationManager.cancel(_id);
}
}
break;
case this.ACTION_TYPE_CLEAR:
{
notificationManager.cancelAll();
const _appid = intent.getStringExtra("_appId");
if (_appid != null) {
const appMsg = PushManager.getInstance().mAppMessages;
appMsg.delete(_appid);
}
}
break;
case this.ACTION_TYPE_CLICK:
{
this.clickHandle(intent, notificationManager);
const packagename = context.getPackageName();// 启动类所在包名
const pm = context.getPackageManager();
const _intent = pm.getLaunchIntentForPackage(packagename);
const appid = intent.getStringExtra("appid");
_intent?.putExtra("appid", appid);
const isStartWeb = intent?.getBooleanExtra("__start_first_web__", false) ?? false;
if (isStartWeb) {
_intent?.putExtra("__start_first_web__", isStartWeb);
_intent?.putExtra("__first_web_url__", intent?.getStringExtra("__first_web_url__"));
}
_intent?.putExtra("__start_from__", 3);
_intent?.putExtra("__payload__", intent?.getStringExtra("payload"));
_intent?.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(_intent);
}
break;
}
}
clickHandle(intent : Intent, _notificationManager : NotificationManager) {
const _bundle = intent.getExtras()!!;
const appid = _bundle.getString("appid");
const uuid = _bundle.getString("uuid");
if (_notificationManager != null) {//作为插件时,手助负责创建通知栏消息
const _id = intent.getIntExtra("id", 0);
_notificationManager.cancel(_id);
}
let _pushMessage : PushMessage | null = null
if (appid != null && uuid != null) {
_pushMessage = this.findPushMessage(appid!!, uuid!!);
}
if (_pushMessage != null) {
let isStartWeb = false;
if (!TextUtils.isEmpty(_pushMessage.mPayload)) {
try {
const payLoadJson = JSON.parseObject(_pushMessage.mPayload ?? "")
const url = payLoadJson?.getString("__adurl")
if (!TextUtils.isEmpty(url)) {
intent.putExtra("__start_first_web__", true);
intent.putExtra("__first_web_url__", url);
isStartWeb = true;
}
} catch (e : Exception) {
e.printStackTrace();
}
}
if (!isStartWeb && !sendEvent("click", _pushMessage)) {
this.addNeedExecClickMessage(_pushMessage);
}
// 点击后的消息,需要移除消息记录,避免getAllMessage时不正确
if (appid != null) {
this.removePushMessage(appid, _pushMessage);
}
} else {
_pushMessage = new PushMessage(_bundle);
if (!TextUtils.isEmpty(_pushMessage.mPayload)) {
try {
const payLoadJson = JSON.parseObject(_pushMessage.mPayload!!)
const url = payLoadJson?.getString("__adurl")
if (!TextUtils.isEmpty(url)) {
intent.putExtra("__start_first_web__", true);
intent.putExtra("__first_web_url__", url);
}
} catch (e : Exception) {
e.printStackTrace();
}
}
this.addNeedExecClickMessage(_pushMessage);
}
_bundle.clear();
}
findPushMessage(pAppid : String, pUuid : String) : PushMessage | null {
let _ret : PushMessage | null = null;
const _arr = this.mAppMessages.get(pAppid);
if (_arr == null) {//若没有通过appid获取到消息集合,则通过uuid遍历所有消息
this.mAppMessages.forEach((value : PushMessage[], key : string) => {
if (value != null) {
value.forEach((value : PushMessage) => {
if (pUuid == value.getMessageUUID()) {
_ret = value
}
})
}
})
} else if (_arr != null) {
_arr.forEach((value : PushMessage) => {
if (pUuid == value.getMessageUUID()) {
_ret = value
}
})
}
return _ret;
}
fileIsExist(path : string) : boolean {
const realPath = UTSAndroid.convert2AbsFullPath(path)
const file = new File(realPath)
return file.exists()
}
}
\ No newline at end of file
import TextUtils from 'android.text.TextUtils'
import Bundle from 'android.os.Bundle';
export class PushMessage {
private mTitle : string | null = null
private contentJson : string | null = null
private mContent : string | null = null
mPayloadJSON : UTSJSONObject | null = null
mPayload : string | null = null
private mWhen : Long = 0
mDelay : Long = 0
private mPath : string | null = null
private mForceNotification : string | null = null
private channelId = ""
private category = ""
private mMessageAppid : string | null = null
private mIconPath : string | null = null
private mUUID : string | null = null
private nID : number = 0
private isCover = false
private sound = "system"
private static mNotificationId = 1
private needCreateNotification = true
private pushVersion : Float = 1.0.toFloat()
private extJSON : UTSJSONObject | null = null
constructor(data : string, defaultTitle : string, isUniPush2 : boolean) {
if (!isUniPush2) {
this.contentJson = data
this.parseJson(data, UTSAndroid.getAppId(), defaultTitle)
} else {
this.extJSON = JSON.parseObject(data)
this.mMessageAppid = UTSAndroid.getAppId()
this.pushVersion = 2.0.toFloat()
if (this.extJSON != null) {
this.channelId = this.extJSON!!.getString("channelId") ?? ""
this.category = this.extJSON!!.getString("category") ?? ""
}
}
this.setMessageUUID()
this.setNotificationID()
}
$constructor(b : Bundle) {
this.mTitle = b.getString("title");
this.mContent = b.getString("content");
this.nID = b.getInt("nId");
this.mWhen = b.getLong("when");
this.sound = b.getString("sound") ?? "system";
this.mMessageAppid = b.getString("appid");
this.mUUID = b.getString("uuid");
this.mPayload = b.getString("payload");
this.mIconPath = b.getString("icon");
this.channelId = b.getString("channelId", "");
this.category = b.getString("category", "");
}
getNeedCreateNotification() : boolean {
return this.needCreateNotification;//payload为空串时需要创建
}
getMessageUUID() : string | null {
return this.mUUID
}
getJsonObject() : UTSJSONObject {
if (this.extJSON != null) {
if (this.pushVersion == (2.0.toFloat())) {
try {
this.extJSON!!["__UUID__"] = this.mUUID
this.extJSON!!["appid"] = this.mMessageAppid
} catch (e : Exception) {
e.printStackTrace()
return {};
}
}
return this.extJSON!!
} else {
const result = {} as UTSJSONObject;
result["__UUID__"] = this.mUUID
result["title"] = this.mTitle
result["appid"] = this.mMessageAppid
result["content"] = this.mContent
if (this.mPayloadJSON != null) {
result["payload"] = this.cleanNullValue(this.mPayloadJSON!!)
} else {
let payLoadObj : UTSJSONObject | null = null
if (this.mPayload != null) {
payLoadObj = JSON.parseObject(this.mPayload!!)
}
if (payLoadObj != null) {
result["payload"] = this.cleanNullValue(payLoadObj)
} else {
result["payload"] = this.mPayload
}
}
if (!TextUtils.isEmpty(this.mPath)) {
result["path"] = this.mPath
}
if (!TextUtils.isEmpty(this.mForceNotification)) {
result["force_notification"] = this.mForceNotification
}
if (!TextUtils.isEmpty(this.channelId)) {
result["channelId"] = this.channelId
}
if (!TextUtils.isEmpty(this.category)) {
result["category"] = this.category
}
return result
}
}
cleanNullValue(json : UTSJSONObject) : UTSJSONObject {
const result = {}
json.toMap().forEach((value, key) => {
if (value != null) {
result[key] = value
}
})
return result
}
toBundle() : Bundle {
const bundle = new Bundle()
if (this.extJSON != null && this.pushVersion == (2.0.toFloat())) {
bundle.putInt("nId", this.nID.toInt());
bundle.putLong("when", this.mWhen);
bundle.putString("sound", this.sound);
bundle.putString("appid", this.mMessageAppid);
bundle.putString("uuid", this.mUUID);
bundle.putString("icon", this.mIconPath);
const map = this.extJSON!!.toMap()
map.forEach((value, key) => {
if (value != null) {
if (typeof value == 'string') {
bundle.putString(key, value as string);
} else if (value instanceof Integer) {
bundle.putInt(key, value as Int);
} else if (value instanceof Double) {
bundle.putDouble(key, value);
} else if (typeof value == 'boolean') {
bundle.putBoolean(key, value as boolean);
} else if (value instanceof UTSJSONObject) {
bundle.putString(key, (value as UTSJSONObject).toJSONString());
}
}
})
return bundle
}
bundle.putString("title", this.mTitle);
bundle.putString("content", this.mContent);
bundle.putInt("nId", this.nID.toInt());
bundle.putLong("when", this.mWhen);
bundle.putString("sound", this.sound);
bundle.putString("appid", this.mMessageAppid);
bundle.putString("uuid", this.mUUID);
if (this.mPayloadJSON != null) {
bundle.putString("payload", this.mPayloadJSON!!.toJSONString());
} else {
bundle.putString("payload", this.mPayload);
}
bundle.putString("icon", this.mIconPath);
bundle.putString("channelId", this.channelId);
bundle.putString("category", this.category);
return bundle
}
private setMessageUUID() : void {
this.mUUID = "androidPushMsg" + this.hashCode()
}
private setNotificationID() : void {
if (!this.isCover) {
PushMessage.mNotificationId++
}
this.nID = PushMessage.mNotificationId
}
/**
* 解析消息的数据
* @param defaultAppid 通过appid 查询到icon资源 , 1.0强需求, 2.0 不需求
*/
private parseJson(data : string, defaultAppid : string, defaultTitle : string) : void {
const json = JSON.parseObject(data)
if (json != null) {
let t_appid = json.getString("appid")
const content = json.getString("content")
if (content != null) {
this.mContent = content
} else {
const message = json.getString("message")
if (message != null) {
this.mContent = message
} else {
this.needCreateNotification = true
this.mContent = data
}
}
if (this.hasOwnProperty(json, "payload")) {
const payloadJson = json.getJSON("payload")
if (payloadJson != null) {
this.mPayloadJSON = payloadJson
} else {
this.mPayload = json.getString("payload")
}
} else {
if (this.hasOwnProperty(json, "Payload")) {
const payloadJson = json.getJSON("Payload")
if (payloadJson != null) {
this.mPayloadJSON = payloadJson
} else {
this.mPayload = json.getString("Payload")
}
} else {
this.needCreateNotification = false
this.mPayload = data
}
}
if (this.hasOwnProperty(json, "title")) {
this.mTitle = json.getString("title")
} else {
this.needCreateNotification = false
this.mTitle = defaultTitle
}
this.isCover = json.getBoolean("cover") ?? false
if ("none" == json.getString("sound")) {
this.sound = "none"
}
this.mWhen = (json.getNumber("when") ?? 0).toLong()
this.mDelay = (json.getNumber("delay") ?? 0).toLong()
this.mPath = json.getString("path")
this.mForceNotification = json.getString("force_notification")
this.channelId = json.getString("channelId") ?? ""
this.category = json.getString("category") ?? ""
if (TextUtils.isEmpty(t_appid)) {
t_appid = defaultAppid
}
this.mMessageAppid = t_appid
const iconPath = json.getString("icon") ?? ""
this.mIconPath = UTSAndroid.convert2AbsFullPath(iconPath)
} else {
this.needCreateNotification = false
this.mContent = data
this.mPayload = data
this.mTitle = defaultTitle
}
}
private hasOwnProperty(jsonObject : UTSJSONObject, key : string) : boolean {
return jsonObject.getAny(key) != null
}
}
\ No newline at end of file
import Context from 'android.content.Context';
import PackageManager from 'android.content.pm.PackageManager';
import Bundle from 'android.os.Bundle';
import TextUtils from 'android.text.TextUtils';
export class PushState {
private static sMetaDatas : Bundle | null = null
static getAutoNotification() : boolean {
const context = UTSAndroid.getAppContext() as Context
const sp = context.getSharedPreferences("push_db_name", Context.MODE_PRIVATE)
const autoNotification = this.getMetaValue(context, "dcloud_unipush_auto_notification")
let needPush = true
if (autoNotification != null) {
if (!autoNotification.equals("ture", true)) {
needPush = false;
}
}
needPush = sp.getBoolean("auto_notification", needPush);
return needPush
}
private static getMetaValue(context : Context, metaKey : string) : string | null {
if (this.sMetaDatas == null) {
try {
this.sMetaDatas = context.getPackageManager().getApplicationInfo(context.getPackageName(), PackageManager.GET_META_DATA).metaData;
} catch (e : Exception) {
e.printStackTrace();
return null;
}
}
if (this.sMetaDatas != null) {
const value = this.sMetaDatas!!.get(metaKey)
if (value != null && !TextUtils.isEmpty(value as string)) {
return value as string;
}
}
return null;
}
}
\ No newline at end of file
export class StringUtil {
static trimString(pSrc : string, removed : string) : string {
const pTrimChar = removed.charAt(0)
let _ret = pSrc;
if (_ret != null && _ret != "") {
const _startPosi = _ret.charAt(0) == pTrimChar ? 1 : 0;
const _count = _ret.length;
const _endPosi = _ret.charAt(_count - 1) == pTrimChar ? _count - 1 : _count;
_ret = _ret.substring(_startPosi, _endPosi);
}
return _ret;
}
static getInt(content : string) : number | null {
try {
return content.toInt();
} catch (e : Exception) {
return null;
}
}
static getDouble(content : string) : number | null {
try {
return content.toDouble()
} catch (e : Exception) {
return null;
}
}
}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<resources
xmlns:tools="http://schemas.android.com/tools"
tools:keep="@layout/getui_notification,
@drawable/push,
@drawable/push_small,
/>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="dcloud_feature_aps_notification_channel">消息推送</string>
<string name="dcloud_feature_aps_notification_group">推送消息</string>
</resources>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="dcloud_feature_aps_notification_channel" >unipush</string>
<string name="dcloud_feature_aps_notification_group" >message push</string>
</resources>
\ No newline at end of file
export interface Uni {
/**
* getPushClientId()
* @description
* 获取客户端唯一的推送标识
* @param {GetPushClientIdOptions}
* @return {void}
* @tutorial http://uniapp.dcloud.io/api/plugins/push.html#getpushclientid
* @uniPlatform {
* "app": {
* "android": {
* "osVer": "4.4",
* "uniVer": "√",
* "unixVer": "3.97"
* },
* "ios": {
* "osVer": "9.0",
* "uniVer": "x",
* "unixVer": "x"
* }
* }
* }
* @example
```typescript
uni.getPushClientId({
complete: (res: any) => {
console.log("getPushClientId complete => " + JSON.stringify(res));
}
});
```
*/
getPushClientId(options : GetPushClientIdOptions) : void;
/**
* onPushMessage()
* @description
* 启动监听推送消息事件
* @param {OnPushMessageCallback}
* @return {void}
* @tutorial http://uniapp.dcloud.io/api/plugins/push.html#onpushmessage
* @uniPlatform {
* "app": {
* "android": {
* "osVer": "4.4",
* "uniVer": "√",
* "unixVer": "3.97"
* },
* "ios": {
* "osVer": "9.0",
* "uniVer": "x",
* "unixVer": "x"
* }
* }
* }
* @example
```typescript
uni.onPushMessage((res : OnPushMessageCallbackResult) => {
console.log("onPushMessage => " + JSON.stringify(res))
});
```
*/
onPushMessage(callback : OnPushMessageCallback) : void;
/**
* offPushMessage()
* @description
* 关闭推送消息监听事件
* @param {OnPushMessageCallback}
* @return {void}
* @tutorial http://uniapp.dcloud.io/api/plugins/push.html#offpushmessage
* @uniPlatform {
* "app": {
* "android": {
* "osVer": "4.4",
* "uniVer": "√",
* "unixVer": "3.97"
* },
* "ios": {
* "osVer": "9.0",
* "uniVer": "x",
* "unixVer": "x"
* }
* }
* }
* @example
```typescript
const cb = (res : OnPushMessageCallbackResult) => {
console.log("onPushMessage => " + JSON.stringify(res))
}
uni.offPushMessage(cb);
```
*/
offPushMessage(callback : OnPushMessageCallback) : void;
/**
* getChannelManager()
* @description
* 获取通知渠道管理器,Android 8系统以上才可以设置通知渠道,Android 8系统以下返回null。
* @param {void}
* @return {ChannelManager}
* @uniPlatform {
* "app": {
* "android": {
* "osVer": "4.4",
* "uniVer": "3.97",
* "unixVer": "3.97"
* },
* "ios": {
* "osVer": "9.0",
* "uniVer": "x",
* "unixVer": "x"
* }
* }
* }
* @example
```typescript
const channelManager = uni.getChannelManager();
channelManager.setPushChannel({
channelId: "test1",
channelDesc: "test1 desc",
soundName: "pushsound"
})
const channels = channelManager.getAllChannels() as string[]
console.log("channels : " + channels);
```
*/
getChannelManager() : ChannelManager;
/**
* createPushMessage()
* @description
* 创建本地通知栏消息
* @param {CreatePushMessageOptions}
* @return {void}
* @tutorial http://uniapp.dcloud.io/api/plugins/push.html#createpushmessage
* @uniPlatform {
* "app": {
* "android": {
* "osVer": "4.4",
* "uniVer": "√",
* "unixVer": "3.97"
* },
* "ios": {
* "osVer": "9.0",
* "uniVer": "x",
* "unixVer": "x"
* }
* }
* }
* @example
```typescript
uni.createPushMessage({
title:"hello",
content: "content"
});
```
*/
createPushMessage(options : CreatePushMessageOptions) : void;
}
export type GetPushClientId = (options : GetPushClientIdOptions) => void;
export type GetPushClientIdSuccess = {
/**
* 个推客户端推送id,对应uni-id-device表的push_clientid
*/
cid : string,
/**
* 错误描述
*/
errMsg : string
};
export type GetPushClientIdSuccessCallback = (result : GetPushClientIdSuccess) => void;
export type GetPushClientIdFail = UniError;
export type GetPushClientIdFailCallback = (result : GetPushClientIdFail) => void;
export type GetPushClientIdComplete = any;
export type GetPushClientIdCompleteCallback = (result : GetPushClientIdComplete) => void;
export type GetPushClientIdOptions = {
/**
* 接口调用成功的回调函数
* @defaultValue null
*/
success : GetPushClientIdSuccessCallback | null,
/**
* 接口调用失败的回调函数
* @defaultValue null
*/
fail : GetPushClientIdFailCallback | null,
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
* @defaultValue null
*/
complete : GetPushClientIdCompleteCallback | null
};
/**
* 事件类型
* - click 从系统推送服务点击消息启动应用事件
* - receive 应用从推送服务器接收到推送消息事件
*/
export type OnPushMessageType = "click" | "receive";
export type OnPushMessageCallbackResult = {
/**
* 事件类型
* @type{OnPushMessageType}
*/
type : OnPushMessageType,
/**
* 消息内容
*/
data : UTSJSONObject
};
export type OnPushMessageCallback = (result : OnPushMessageCallbackResult) => void;
export type OnPushMessage = (callback : OnPushMessageCallback) => void;
export type OffPushMessage = (callback : OnPushMessageCallback) => void;
export type GetChannelManager = () => ChannelManager;
export type SetPushChannelOptions = {
/**
* 添加的声音文件,注意raw目录下必须要有 ,不传此字段将使用默认铃音。
* @defaultValue null
*/
soundName? : string | null,
/**
* 通知渠道id
*/
channelId : string,
/**
* 通知渠道描述
*/
channelDesc : string,
/**
* 呼吸灯闪烁
* @defaultValue false
*/
enableLights? : boolean | null,
/**
* 震动
* @defaultValue false
*/
enableVibration? : boolean | null,
/**
* 通知的重要性级别,可选范围IMPORTANCE_LOW:2、IMPORTANCE_DEFAULT:3、IMPORTANCE_HIGH:4 。
* @defaultValue 3
*/
importance? : number | null,
/**
* 锁屏可见性,可选范围VISIBILITY_PRIVATE:0、VISIBILITY_PUBLIC:1、VISIBILITY_SECRET:-1、VISIBILITY_NO_OVERRIDE:-1000。
* @defaultValue -1000
*/
lockscreenVisibility? : number | null
}
export interface ChannelManager {
/**
* 设置推送渠道
*
* @uniPlatform {
* "app": {
* "android": {
* "osVer": "4.4",
* "uniVer": "√",
* "unixVer": "3.97"
* },
* "ios": {
* "osVer": "9.0",
* "uniVer": "x",
* "unixVer": "x"
* }
* }
* }
*/
setPushChannel(options : SetPushChannelOptions) : void;
/**
* 获取当前应用注册的所有的通知渠道。
*
* @uniPlatform {
* "app": {
* "android": {
* "osVer": "4.4",
* "uniVer": "√",
* "unixVer": "3.97"
* },
* "ios": {
* "osVer": "9.0",
* "uniVer": "x",
* "unixVer": "x"
* }
* }
* }
*/
getAllChannels() : Array<string>;
}
export type CreatePushMessage = (options : CreatePushMessageOptions) => void;
export type CreatePushMessageSuccess = {};
export type CreatePushMessageSuccessCallback = (result : CreatePushMessageSuccess) => void;
export type CreatePushMessageFail = UniError;
export type CreatePushMessageFailCallback = (result : CreatePushMessageFail) => void;
export type CreatePushMessageComplete = any;
export type CreatePushMessageCompleteCallback = (result : CreatePushMessageComplete) => void;
export type CreatePushMessageOptions = {
/**
* 是否覆盖上一次提示的消息
* @type boolean
* @defaultValue false
*/
cover? : boolean | null,
/**
* 提示消息延迟显示的时间,单位为s
* @defaultValue 0
*/
delay? : number | null,
/**
* 推送消息的图标
* @defaultValue null
*/
icon? : string | null,
/**
* 推送消息的提示音
* - system: 使用系统通知提示音(默认值)
* - none: 不使用提示音
* @type 'system' | 'none'
* @defaultValue "system"
*/
sound? : string | null,
/**
* 推送消息的标题
* @defaultValue ""
*/
title? : string | null,
/**
* 消息显示的内容,在系统通知中心中显示的文本内容
*/
content : string,
/**
* 消息承载的数据,可根据业务逻辑自定义数据格式
* @defaultValue null
*/
payload? : any | null,
/**
* 消息上显示的提示时间
* @defaultValue 当前时间
*/
when? : number | null,
/**
* 渠道id
* @defaultValue "DcloudChannelID"
* @uniPlatform {
* "app": {
* "android": {
* "osVer": "4.4",
* "uniVer": "√",
* "unixVer": "3.97"
* },
* "ios": {
* "osVer": "9.0",
* "uniVer": "x",
* "unixVer": "x"
* }
* }
* }
*/
channelId? : string | null,
/**
* 通知类别
* @defaultValue null
* @uniPlatform {
* "app": {
* "android": {
* "osVer": "4.4",
* "uniVer": "√",
* "unixVer": "3.97"
* },
* "ios": {
* "osVer": "9.0",
* "uniVer": "x",
* "unixVer": "x"
* }
* }
* }
*/
category? : string | null,
/**
* 接口调用成功的回调函数
* @defaultValue null
*/
success : CreatePushMessageSuccessCallback | null,
/**
* 接口调用失败的回调函数
* @defaultValue null
*/
fail : CreatePushMessageFailCallback | null,
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
* @defaultValue null
*/
complete : CreatePushMessageCompleteCallback | null
};
declare namespace UniNamespace {
type OnUserCaptureScreenCallback = (res?: { errMsg: string }) => void
/**
* uni.onUserCaptureScreen/uni.offUserCaptureScreen回调参数
*/
type OnUserCaptureScreenCallbackResult = {
/**
* 截屏文件路径(仅Android返回)
*/
path ?: string
}
/**
* uni.onUserCaptureScreen/uni.offUserCaptureScreen回调函数定义
*/
type UserCaptureScreenCallback = (res : OnUserCaptureScreenCallbackResult) => void
type OnUserCaptureScreen = (callback : UserCaptureScreenCallback | null) => void
type OffUserCaptureScreen = (callback : UserCaptureScreenCallback | null) => void
/**
* uni.setUserCaptureScreen成功回调参数
*/
type SetUserCaptureScreenSuccess = {
}
/**
* uni.setUserCaptureScreen成功回调函数定义
*/
type SetUserCaptureScreenSuccessCallback = (res : SetUserCaptureScreenSuccess) => void
/**
* 错误码
* - 12001 "setUserCaptureScreen:system not support"
* - 12010 "setUserCaptureScreen:system internal error"
*/
type SetUserCaptureScreenErrorCode = 12001 | 12010;
/**
* SetUserCaptureScreen 的错误回调参数
*/
interface SetUserCaptureScreenFail {
errCode : SetUserCaptureScreenErrorCode
}
/**
* uni.setUserCaptureScreen失败回调函数定义
*/
type SetUserCaptureScreenFailCallback = (res : SetUserCaptureScreenFail) => void
/**
* uni.setUserCaptureScreen完成回调函数定义
*/
type SetUserCaptureScreenCompleteCallback = (res : any) => void
/**
* uni.setUserCaptureScreen参数
*/
type SetUserCaptureScreenOptions = {
/**
* true: 允许用户截屏 false: 不允许用户截屏,防止用户截屏到应用页面内容
*/
enable : boolean;
/**
* 接口调用成功的回调函数
*/
// success : SetUserCaptureScreenSuccessCallback | null,
success ?: SetUserCaptureScreenSuccessCallback,
/**
* 接口调用失败的回调函数
*/
// fail : SetUserCaptureScreenFailCallback | null,
fail ?: SetUserCaptureScreenFailCallback,
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
// complete : SetUserCaptureScreenSuccessCallback | SetUserCaptureScreenFailCallback | null
complete ?: SetUserCaptureScreenCompleteCallback
}
type SetUserCaptureScreen = (options : SetUserCaptureScreenOptions) => void
}
declare interface Uni {
/**
* 监听用户主动截屏事件,用户使用系统截屏按键截屏时触发此事件。
* 开启截屏监听
*
* @param {UserCaptureScreenCallback} callback
* @tutorial https://uniapp.dcloud.net.cn/api/system/capture-screen.html#onusercapturescreen
* @uniPlatform {
* "app": {
* "android": {
* "osVer": "4.4.4",
* "uniVer": "3.7.7",
* "unixVer": "3.9.0"
* },
* "ios": {
* "osVer": "9.0",
* "uniVer": "3.7.7",
* "unixVer": "3.9.0"
* }
* }
* }
* @uniVersion 3.7.7
* @uniVueVersion 2,3 //支持的vue版本
* @autotest { expectCallback: true }
*/
onUserCaptureScreen(callback : UniNamespace.UserCaptureScreenCallback | null) : void,
/**
* 关闭截屏监听
*
* 文档: [https://uniapp.dcloud.net.cn/api/system/capture-screen.html#onusercapturescreen](https://uniapp.dcloud.net.cn/api/system/capture-screen.html#onusercapturescreen)
* @param {UserCaptureScreenCallback} callback
* @tutorial https://uniapp.dcloud.net.cn/api/system/capture-screen.html#offusercapturescreen
* @uniPlatform {
* "app": {
* "android": {
* "osVer": "4.4.4",
* "uniVer": "3.7.7",
* "unixVer": "3.9.0"
* },
* "ios": {
* "osVer": "9.0",
* "uniVer": "3.7.7",
* "unixVer": "3.9.0"
* }
* }
* }
* @uniVersion 3.7.7
* @uniVueVersion 2,3 //支持的vue版本
* @autotest { expectCallback: true }
*/
onUserCaptureScreen(callback: UniNamespace.OnUserCaptureScreenCallback): void;
offUserCaptureScreen(callback : UniNamespace.UserCaptureScreenCallback | null) : void,
/**
* 用户主动截屏事件。取消事件监听。
* 设置防截屏
*
* 文档: [https://uniapp.dcloud.net.cn/api/system/capture-screen.html#offusercapturescreen](https://uniapp.dcloud.net.cn/api/system/capture-screen.html#offusercapturescreen)
* @param {SetUserCaptureScreenOptions} options
* @tutorial https://uniapp.dcloud.net.cn/api/system/capture-screen.html#setusercapturescreen
* @uniPlatform {
* "app": {
* "android": {
* "osVer": "4.4.4",
* "uniVer": "3.7.7",
* "unixVer": "3.9.0"
* },
* "ios": {
* "osVer": "13.0",
* "uniVer": "3.7.7",
* "unixVer": "3.9.0"
* }
* }
* }
* @uniVersion 3.7.7
* @uniVueVersion 2,3 //支持的vue版本
*/
offUserCaptureScreen(callback: UniNamespace.OnUserCaptureScreenCallback): void;
setUserCaptureScreen(options : UniNamespace.SetUserCaptureScreenOptions) : void
}
\ No newline at end of file
import Context from "android.content.Context";
import { UTSAndroid } from "io.dcloud.uts";
import WifiManager from "android.net.wifi.WifiManager";
import WifiInfo from "android.net.wifi.WifiInfo";
import Manifest from "android.Manifest";
......@@ -8,9 +7,7 @@ import ScanResult from "android.net.wifi.ScanResult";
import BroadcastReceiver from "android.content.BroadcastReceiver";
import ActivityCompat from "androidx.core.app.ActivityCompat";
import IntentFilter from "android.content.IntentFilter";
import JSONObject from "com.alibaba.fastjson.JSONObject";
import Intent from "android.content.Intent";
import Thread from "java.lang.Thread";
import WifiConfiguration from 'android.net.wifi.WifiConfiguration';
import AuthAlgorithm from 'android.net.wifi.WifiConfiguration.AuthAlgorithm';
......@@ -18,8 +15,8 @@ import KeyMgmt from 'android.net.wifi.WifiConfiguration.KeyMgmt';
import TextUtils from 'android.text.TextUtils';
import Build from 'android.os.Build';
import { UniWifiResult, GetConnectedWifiOptions, WifiConnectOption, WifiOption, UniWifiInfo } from "../interface.uts"
import { UniWifiResult, UniWifiInfoWithPartialInfo,GetConnectedWifiOptions, WifiConnectOption, WifiOption, UniWifiInfo,UniWifiCallback ,UniWifiResultCallback,UniWifiResultCallbackWithPartialInfo,UniGetWifiListCallback} from "../interface.uts"
import { WifiFailImpl, getErrcode,UniErrorSubject } from '../unierror';
/**
......@@ -32,12 +29,12 @@ class Global {
// 扫描wifi结果
static scanList : AndroidUniWifiInfo[] = []
// 获取wifi列表监听
static onGetWifiListCallback : UTSCallback | null = null
static supendGetWifiSuccess : ((res: UniWifiResult) => void) | null = null
static supendGetWifiComplete : ((res: UniWifiResult) => void) | null = null
static onGetWifiListCallback : UniGetWifiListCallback|null = null
static supendGetWifiSuccess : UniWifiResultCallback|null = null
static supendGetWifiComplete :UniWifiResultCallback|null = null
// wifi链接监听
static onWifiConnectCallbackList : UTSCallback[] = []
static onWifiConnectWithPartialInfoCallbackList : UTSCallback[] = []
static onWifiConnectCallbackList : UniWifiResultCallback[] = []
static onWifiConnectWithPartialInfoCallbackList : UniWifiResultCallbackWithPartialInfo[] = []
}
......@@ -256,45 +253,36 @@ class CustomBroadcastReceiver extends BroadcastReceiver {
if (intent.action == WifiManager.WIFI_STATE_CHANGED_ACTION) {
let state =
intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_UNKNOWN)
if (state == WifiManager.WIFI_STATE_ENABLED) {
// 获取当前的connectInfo 并且进行数据封装
// let uniWifiInfo = new UniWifiInfo(null)
let uniWifiInfo : UniWifiInfo = {
SSID: "",
secure: false,
signalStrength: 0,
frequency: 0,
}
let uniWifiInfo = new UniWifiInfo("","",false,0,0)
//做一些异步操作
setTimeout(function () {
// BroadcastReceiver 中不能执行耗时任务,需要使用setTimeout
// @ts-ignore
let winfo = this.mWifiManager!.getConnectionInfo();
while (winfo.bssid == null || zeroCountNum(winfo.bssid) > 4) {
Thread.sleep(1000)
winfo = this.mWifiManager!.getConnectionInfo();
}
// 封装成数据对象
if(winfo != null && winfo.bssid != null && zeroCountNum(winfo.bssid) < 3){
// 当前设备链接到了某个具体的wifi.封装成数据对象
uniWifiInfo = wrapUniWifiInfoFromConnectInfo(winfo)
let res = {
errMsg: 'onWifiConnected:ok',
errCode: 0,
wifi: uniWifiInfo
}
let res = new UniWifiResult(0,UniErrorSubject,'onWifiConnected:ok',uniWifiInfo)
// wifi状态可用了,分发当前的链接状态给已注册的监听集合
for (let perCallback in Global.onWifiConnectCallbackList) {
perCallback(res);
}
// 封装仅SSID 数据对象
var connectedWithPartialInfo = {
SSID: uniWifiInfo.SSID
}
let connectedWithPartialInfo = new UniWifiInfoWithPartialInfo(uniWifiInfo.SSID)
for (let perCallback in Global.onWifiConnectWithPartialInfoCallbackList) {
perCallback(connectedWithPartialInfo);
}
} else {
// 开启了wifi 开关,但是尚未链接到某个具体的wifi
}
}, 100);
......@@ -305,14 +293,9 @@ class CustomBroadcastReceiver extends BroadcastReceiver {
if (intent.action == WifiManager.SCAN_RESULTS_AVAILABLE_ACTION) {
startWifiScaning = false;
// wifi 扫描结果回调
let results = this.mWifiManager!.scanResults;
if (results != null) {
Global.scanList = []
for (let scanResult in results) {
......@@ -324,7 +307,7 @@ class CustomBroadcastReceiver extends BroadcastReceiver {
// 挨个通知,所有的监听器
if(Global.onGetWifiListCallback != null){
const data = new JSONObject();
const data = new UTSJSONObject();
data["wifiList"] = Global.scanList
Global.onGetWifiListCallback?.(data);
/**
......@@ -335,11 +318,7 @@ class CustomBroadcastReceiver extends BroadcastReceiver {
}
let ret : UniWifiResult = {
errCode: 0,
errSubject: "uni-getWifiList",
errMsg: "getWifiList:ok"
}
let ret = new UniWifiResult(0,UniErrorSubject,"getWifiList:ok",null)
if(Global.supendGetWifiSuccess != null){
Global.supendGetWifiSuccess?.(ret)
Global.supendGetWifiSuccess = null
......@@ -365,29 +344,8 @@ var startWifiScaning = false
* 开启wifi
*/
@Suppress("DEPRECATION")
export function startWifi(option : WifiOption) {
// 需要先开启wifi,才能使用后续的功能
let requestCode = 1001;
let permissionWifi = arrayOf("android.permission.ACCESS_FINE_LOCATION");
let result : UniWifiResult = {
errCode: 12001,
errMsg: "startWifi:premission loss",
errSubject: "uni-startWifi"
}
// 检查权限
if (ActivityCompat.checkSelfPermission(UTSAndroid.getUniActivity()!, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(UTSAndroid.getUniActivity()!, permissionWifi, requestCode.toInt())
// 尚不具备权限,返回错误
let err = new UniError("uni-startWifi",12001,"startWifi:premission loss");
option.fail?.(err)
option.complete?.(err)
export function startWifiImpl(option : WifiOption) {
return;
}
// 具备了权限,继续前进
let wifiManager : WifiManager =
......@@ -395,16 +353,15 @@ export function startWifi(option : WifiOption) {
// 用户没有开启wifi 总开关
if (!wifiManager.isWifiEnabled()) {
// wifi 没开启
let err = new UniError("uni-startWifi",12005,"wifi not turned on");
option.fail?.(err);
option.complete?.(err);
let failResult = new WifiFailImpl(getErrcode(12005));
option.fail?.(failResult);
option.complete?.(failResult);
return;
}
// 初始化wifi 状态广播监听,后续所有的api,均基于此
if(Global.mReceiver != null){
// 说明已经注册过了
result.errCode = 0
result.errMsg = "startWifi:ok"
let result = UniWifiResult(0,UniErrorSubject,"startWifi:ok",null)
option.success?.(result)
option.complete?.(result)
......@@ -443,14 +400,32 @@ export function startWifi(option : WifiOption) {
// 开始扫描
wifiManager.startScan()
result.errCode = 0
result.errMsg = "startWifi:ok"
let result = UniWifiResult(0,UniErrorSubject,"startWifi:ok",null)
option.success?.(result)
option.complete?.(result)
}
@Suppress("DEPRECATION")
export function startWifi(option : WifiOption) {
/**
* 准备权限
*/
let permissionNeed = ["android.permission.ACCESS_FINE_LOCATION"];
UTSAndroid.requestSystemPermission(UTSAndroid.getUniActivity()!, permissionNeed, function (allRight:boolean,_grantedList:string[]) {
if (allRight) {
// 交给目前的location 引擎,真实执行
startWifiImpl(option)
}
}, function (_doNotAskAgain:boolean,_grantedList:string[]) {
let err = new WifiFailImpl(getErrcode(12001));
option.fail?.(err)
option.complete?.(err)
})
}
/**
* 获取wifi列表
*/
......@@ -460,8 +435,7 @@ export function getWifiList(option : WifiOption) {
if (Global.mReceiver == null) {
// 还没调用startWifi 提示报错
let err = new UniError("uni-getWifiList",12000,"getWifiList:fail:not invoke startWifi");
let err = new WifiFailImpl(getErrcode(12000));
option.fail?.(err)
option.complete?.(err)
......@@ -471,14 +445,15 @@ export function getWifiList(option : WifiOption) {
let wifiManager : WifiManager =
UTSAndroid.getAppContext()!.getSystemService(Context.WIFI_SERVICE) as WifiManager
if(option.success != null){
Global.supendGetWifiSuccess = option.success
}
if(option.complete != null){
Global.supendGetWifiComplete = option.complete
}
wifiManager.startScan()
}
......@@ -486,12 +461,12 @@ export function getWifiList(option : WifiOption) {
/**
* wifi 链接成功的回调注册
*/
export function onWifiConnected(callback : UTSCallback) {
export function onWifiConnected(callback : UniWifiResultCallback) {
Global.onWifiConnectCallbackList.push(callback)
}
export function onWifiConnectedWithPartialInfo(callback : UTSCallback) {
export function onWifiConnectedWithPartialInfo(callback : UniWifiResultCallbackWithPartialInfo) {
Global.onWifiConnectWithPartialInfoCallbackList.push(callback)
}
......@@ -499,7 +474,7 @@ export function onWifiConnectedWithPartialInfo(callback : UTSCallback) {
/**
* wifi 链接成功的回调取消注册
*/
export function offWifiConnected(callback? : UTSCallback) {
export function offWifiConnected(callback? : UniWifiResultCallback) {
if(callback == null){
Global.onWifiConnectCallbackList = []
......@@ -515,7 +490,7 @@ export function offWifiConnected(callback? : UTSCallback) {
/**
* 不具备详细信息的wifi 反注册
*/
export function offWifiConnectedWithPartialInfo(callback? : UTSCallback) {
export function offWifiConnectedWithPartialInfo(callback? : UniWifiResultCallbackWithPartialInfo) {
if(callback == null){
Global.onWifiConnectWithPartialInfoCallbackList = []
......@@ -531,14 +506,14 @@ export function offWifiConnectedWithPartialInfo(callback? : UTSCallback) {
/**
* 注册Wifi列表的监听事件
*/
export function onGetWifiList(callback : UTSCallback) {
export function onGetWifiList(callback : UniGetWifiListCallback) {
Global.onGetWifiListCallback = callback
}
/**
* 取消注册Wifi列表的监听事件
*/
export function offGetWifiList(callback? : UTSCallback) {
export function offGetWifiList(callback? : UniWifiCallback) {
Global.onGetWifiListCallback = null
Global.supendGetWifiComplete = null
Global.supendGetWifiSuccess = null
......@@ -552,7 +527,7 @@ function realWifiConnect(option : WifiConnectOption){
if (Global.mReceiver == null || Global.scanList.length < 1) {
let err = new UniError("uni-connectWifi",12000,"connectWifi:fail:not invoke startWifi");
let err = new WifiFailImpl(getErrcode(12000));
option.fail?.(err)
option.complete?.(err)
......@@ -569,7 +544,7 @@ function realWifiConnect(option : WifiConnectOption){
if (scanWifiInfo == null) {
// 不在扫描列表中返回错误
let err = new UniError("uni-connectWifi",12000,"connectWifi:fail:not invoke startWifi");
let err = new WifiFailImpl(getErrcode(12000));
option.fail?.(err)
option.complete?.(err)
return
......@@ -597,12 +572,12 @@ function realWifiConnect(option : WifiConnectOption){
// add since 2023-03-28,如果当前系统大于等于android10, 则明确当前系统不支持
if(Build.VERSION.SDK_INT > 28){
// 系统大于android 9
let err = new UniError("uni-connectWifi",12001,"connectWifi:system not support");
let err = new WifiFailImpl(getErrcode(12001));
option.fail?.(err)
option.complete?.(err)
}else{
// 移除之前的配置失败了,返回错误,需要用户手动取消保存一下
let err = new UniError("uni-connectWifi",12013,"connectWifi:wifi config may be expired");
let err = new WifiFailImpl(getErrcode(12013));
option.fail?.(err)
option.complete?.(err)
}
......@@ -627,9 +602,7 @@ function realWifiConnect(option : WifiConnectOption){
let netID = wifiManager.addNetwork(wifiConfigration);
// 如果-1 说明没添加上,报错即可
if (netID < 0) {
let err = new UniError("uni-connectWifi",12002,"connectWifi:password error Wi-Fi");
let err = new WifiFailImpl(getErrcode(12002));
option.fail?.(err)
option.complete?.(err)
......@@ -639,9 +612,7 @@ function realWifiConnect(option : WifiConnectOption){
let enabled = wifiManager.enableNetwork(netID, true);
if (!enabled) {
let err = new UniError("uni-connectWifi",12007,"connectWifi:user denied");
let err = new WifiFailImpl(getErrcode(12007));
option.fail?.(err)
option.complete?.(err)
......@@ -657,17 +628,13 @@ function realWifiConnect(option : WifiConnectOption){
if (!connected) {
// 出错了,返回错误
// 兜底的报错
let err = new UniError("uni-connectWifi",12010,"connectWifi:fail:unknown error");
let err = new WifiFailImpl(getErrcode(12010));
option.fail?.(err)
option.complete?.(err)
return
}
let result : UniWifiResult = {
errCode: 0,
errMsg: "connectWifi:ok",
errSubject: "uni-connectWifi",
}
let result = new UniWifiResult(0,UniErrorSubject,"getWifiList:ok",null)
wifiManager.saveConfiguration()
//scanWifiInfo 根据 partialInfo 填充给返回字段
......@@ -696,11 +663,8 @@ export function connectWifi(option : WifiConnectOption) {
let manunalIntent = new Intent(android.provider.Settings.ACTION_WIFI_SETTINGS);
UTSAndroid.getUniActivity()!.startActivity(manunalIntent);
let result : UniWifiResult = {
errCode: 0,
errMsg: "connectWifi:ok",
errSubject: "uni-connectWifi",
}
let result = new UniWifiResult(0,UniErrorSubject,"connectWifi:ok",null)
option.success?.(result)
option.complete?.(result)
......@@ -741,7 +705,7 @@ export function connectWifi(option : WifiConnectOption) {
export function stopWifi(option : WifiOption) {
// 需要先开启wifi,才能使用后续的功能
if (Global.mReceiver == null) {
let err = new UniError("uni-stopWifi",12000,"stopWifi:not init");
let err = new WifiFailImpl(getErrcode(12000));
option.fail?.(err)
option.complete?.(err)
......@@ -759,14 +723,9 @@ export function stopWifi(option : WifiOption) {
Global.onWifiConnectCallbackList = []
Global.mReceiver = null
let result : UniWifiResult = {
errCode: 0,
errSubject: "uni-stopWifi",
errMsg: "stopWifi:ok"
}
option.success?.(result)
option.complete?.(result)
let ret = new UniWifiResult(0,UniErrorSubject,"stopWifi:ok",null)
option.success?.(ret)
option.complete?.(ret)
}
......@@ -783,7 +742,7 @@ export function getConnectedWifi(option : GetConnectedWifiOptions) {
if (Global.mReceiver == null) {
// 还没调用startWifi 提示报错
let err = new UniError("uni-getConnectedWifi",12000,"getConnectedWifi:fail:not invoke startWifi");
let err = new WifiFailImpl(getErrcode(12000));
option.fail?.(err)
option.complete?.(err)
......@@ -793,7 +752,7 @@ export function getConnectedWifi(option : GetConnectedWifiOptions) {
// 需要先校验权限,没有位置权限无法获取wifi
if (ActivityCompat.checkSelfPermission(UTSAndroid.getUniActivity()!, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// 尚不具备权限,返回错误
let err = new UniError("uni-getConnectedWifi",12001,"getConnectedWifi:permission loss");
let err = new WifiFailImpl(getErrcode(12001));
option.fail?.(err)
option.complete?.(err)
return;
......@@ -812,11 +771,7 @@ export function getConnectedWifi(option : GetConnectedWifiOptions) {
wifiInfo = wrapUniWifiInfoFromConnectInfo(winfo);
let res : UniWifiResult = {
errCode: 0,
errMsg: "getConnectedWifi:ok",
errSubject: "uni-getConnectedWifi",
}
let res = new UniWifiResult(0,UniErrorSubject,"getConnectedWifi:ok",null)
// 判断一下是否wifi 关闭了
if (option.partialInfo!= null) {
......@@ -826,7 +781,7 @@ export function getConnectedWifi(option : GetConnectedWifiOptions) {
res.wifi = ret;
} else {
if (wifiInfo.BSSID == null || zeroCountNum(wifiInfo.BSSID) > 3) {
let err = new UniError("uni-getConnectedWifi",12005,"getConnectedWifi:fail:wifi is disable");
let err = new WifiFailImpl(getErrcode(12005));
option.fail?.(err)
option.complete?.(err)
return
......@@ -840,7 +795,7 @@ export function getConnectedWifi(option : GetConnectedWifiOptions) {
return
}
let err = new UniError("uni-getConnectedWifi",12000,"getConnectedWifi:fail:not invoke startWifi");
let err = new WifiFailImpl(getErrcode(12000));
option.fail?.(err)
option.complete?.(err)
}
......
......@@ -3,7 +3,8 @@ import { CaptiveNetwork, kCNNetworkInfoKeySSID, kCNNetworkInfoKeyBSSID } from 'S
import { NSArray, NSDictionary } from 'Foundation';
import { CFString } from 'CoreFoundation';
import { UIDevice } from 'UIKit';
import { WifiOption, WifiConnectOption, GetConnectedWifiOptions, UniWifiInfo, UniWifiResult, UniWifiCallback, StartWifi, StopWifi, GetWifiList, OnGetWifiList, OffGetWifiList, GetConnectedWifi, ConnectWifi, OnWifiConnected, OnWifiConnectedWithPartialInfo, OffWifiConnected, OnOffWifiConnectedWithPartialInfo, SetWifiList } from "../interface.uts"
import { UniWifiResultCallbackWithPartialInfo, UniGetWifiListCallback, UniWifiResultCallback, WifiOption, WifiConnectOption, GetConnectedWifiOptions, UniWifiInfo, UniWifiResult, UniWifiCallback, StartWifi, StopWifi, GetWifiList, OnGetWifiList, OffGetWifiList, GetConnectedWifi, ConnectWifi, OnWifiConnected, OnWifiConnectedWithPartialInfo, OffWifiConnected, OffWifiConnectedWithPartialInfo, SetWifiList } from "../interface.uts"
import { WifiFailImpl, getErrcode } from '../unierror';
/*
* 系统定位权限获取类
......@@ -114,12 +115,12 @@ function fetchConnectedWifiWithLocationPromise(option: GetConnectedWifiOptions)
option.success?.(res)
option.complete?.(res)
}else {
let err = new UniError("uni-getConnectedWifi",12010,"getConnectedWifi:system internal error");
let err = new WifiFailImpl(getErrcode(12010));
option.fail?.(err)
option.complete?.(err)
}
}else {
let err = new UniError("uni-getConnectedWifi",12010,"getConnectedWifi:system internal error");
let err = new WifiFailImpl(getErrcode(12010));
option.fail?.(err)
option.complete?.(err)
}
......@@ -173,7 +174,7 @@ export const stopWifi: StopWifi = function (option: WifiOption) {
* 获取wifi列表, 在调用之前需要引导用户跳转到系统设置-WIFI设置页面,系统搜索周边wifi后app才能接收到回调
*/
export const getWifiList: GetWifiList = function (option: WifiOption) {
let err = new UniError("uni-getWifiList",12001,"getWifiList:system not support");
let err = new WifiFailImpl(getErrcode(12001));
option.fail?.(err)
option.complete?.(err)
}
......@@ -181,7 +182,7 @@ export const getWifiList: GetWifiList = function (option: WifiOption) {
/* 获取wifi列表的回调
* note: 请在getWifiList方法的回调里调用该方法
*/
export const onGetWifiList: OnGetWifiList = function (callback: UniWifiCallback) {
export const onGetWifiList: OnGetWifiList = function (callback: UniGetWifiListCallback) {
}
......@@ -198,7 +199,7 @@ export const offGetWifiList: OffGetWifiList = function (callback: UniWifiCallbac
*/
export const getConnectedWifi: GetConnectedWifi = function (option: GetConnectedWifiOptions) {
if (UniWiFiModuleGloabInfo.alreadyStartWifi == false) {
let err = new UniError("uni-getConnectedWifi",12000,"getConnectedWifi:not init");
let err = new WifiFailImpl(getErrcode(12000));
option.fail?.(err)
option.complete?.(err)
} else{
......@@ -207,7 +208,7 @@ export const getConnectedWifi: GetConnectedWifi = function (option: GetConnected
if (success == true) {
fetchConnectedWifiWithLocationPromise(option)
}else {
let err = new UniError("uni-getConnectedWifi",12007,"getConnectedWifi:user denied");
let err = new WifiFailImpl(getErrcode(12007));
option.fail?.(err)
option.complete?.(err)
}
......@@ -223,7 +224,7 @@ export const getConnectedWifi: GetConnectedWifi = function (option: GetConnected
*/
export const connectWifi: ConnectWifi = function (option: WifiConnectOption) {
let err = new UniError("uni-connectWifi",12001,"connectWifi:system not support");
let err = new WifiFailImpl(getErrcode(12001));
option.fail?.(err)
option.complete?.(err)
}
......@@ -232,14 +233,14 @@ export const connectWifi: ConnectWifi = function (option: WifiConnectOption) {
/*
* 连上wifi事件的监听函数
*/
export const onWifiConnected: OnWifiConnected = function (callback: UniWifiCallback) {
export const onWifiConnected: OnWifiConnected = function (callback: UniWifiResultCallback) {
}
/*
* 连上wifi事件的监听函数, wifiInfo仅包含ssid
*/
export const onWifiConnectedWithPartialInfo: OnWifiConnectedWithPartialInfo = function (callback: UniWifiCallback) {
export const onWifiConnectedWithPartialInfo: OnWifiConnectedWithPartialInfo = function (callback: UniWifiResultCallbackWithPartialInfo) {
}
......@@ -253,7 +254,7 @@ export const offWifiConnected: OffWifiConnected = function (callback: UniWifiCal
/*
* 移除连接上wifi的事件的监听函数,不传此参数则移除所有监听函数。
*/
export const onOffWifiConnectedWithPartialInfo: OnOffWifiConnectedWithPartialInfo = function (callback: UniWifiCallback | null) {
export const offWifiConnectedWithPartialInfo: OffWifiConnectedWithPartialInfo = function (callback: UniWifiResultCallbackWithPartialInfo | null) {
}
......@@ -261,7 +262,7 @@ export const onOffWifiConnectedWithPartialInfo: OnOffWifiConnectedWithPartialInf
* 设置 wifiList 中 AP 的相关信息。在 onGetWifiList 回调后调用,iOS特有接口。
*/
export const setWifiList: SetWifiList = function (option: WifiOption) {
let err = new UniError("uni-setWifiList",12001,"setWifiList:system not support");
let err = new WifiFailImpl(getErrcode(12001));
option.fail?.(err)
option.complete?.(err)
}
declare namespace UniNamespace {
type UniWifiComplete = any
type WifiSuccessCallback = (res : UniWifiResult) => void
type WifiFailCallback = (err : UniWifiFail) => void
type WifiCompleteCallback = (res : UniWifiComplete) => void
type UniWifiCallback = () => void
type WifiErrorCode = 1300002
interface UniWifiInfo {
SSID : string;
BSSID ?: string;
secure ?: boolean;
signalStrength ?: number;
frequency ?: number;
}
interface UniWifiResult {
errCode : number,
errSubject : string,
errMsg : string,
wifi : UniWifiInfo | null
}
interface UniWifiFail {
errCode : WifiErrorCode
}
interface WifiConnectOption {
SSID : string | null;
BSSID : string | null;
password : string | null;
maunal : boolean | null;
partialInfo : boolean | null; //ios不生效
success : WifiSuccessCallback | null;
fail : WifiFailCallback | null;
complete : WifiCompleteCallback | null;
}
interface GetConnectedWifiOptions {
partialInfo : boolean | null;
success : WifiSuccessCallback | null;
fail : WifiFailCallback | null;
complete ?: WifiCompleteCallback | null;
}
interface WifiOption {
success : WifiSuccessCallback | null,
fail : WifiFailCallback | null,
complete : InstallApkCompleteCallback | null
}
interface UniWifiInfoWithPartialInfo {
SSID : string;
}
type UniGetWifiListCallback = (wifiInfo:UTSJSONObject) => void
type UniWifiResultCallback = (wifiInfo:UniWifiResult) => void
type UniWifiResultCallbackWithPartialInfo = (wifiInfo:UniWifiInfoWithPartialInfo) => void
}
declare interface Uni {
/**
* 初始化Wi-Fi模块
*
* @param {WifiOption} option
* @tutorial https://uniapp.dcloud.net.cn/api/system/wifi.html#startwifi
* @uniPlatform {
* "app": {
* "android": {
* "osVer": "4.4.4",
* "uniVer": "3.7.0",
* "unixVer": "3.9.0"
* },
* "ios": {
* "osVer": "9.0",
* "uniVer": "3.7.7",
* "unixVer": "3.9.0"
* }
* }
* }
* @uniVersion 3.7.7
* @uniVueVersion 2,3 //支持的vue版本
* @autotest { after: 'stopWifi' }
*/
startWifi(option : UniNamespace.WifiOption): void,
/**
* 关闭 Wi-Fi 模块
*
* @param {WifiOption} option
* @tutorial https://uniapp.dcloud.net.cn/api/system/wifi.html#stopwifi
* @uniPlatform {
* "app": {
* "android": {
* "osVer": "4.4.4",
* "uniVer": "3.7.0",
* "unixVer": "3.9.0"
* },
* "ios": {
* "osVer": "9.0",
* "uniVer": "3.7.7",
* "unixVer": "3.9.0"
* }
* }
* }
* @uniVersion 3.7.7
* @uniVueVersion 2,3 //支持的vue版本
* @autotest { before: 'startWifi' }
*/
stopWifi(option : UniNamespace.WifiOption) : void,
/**
* @param {WifiConnectOption} option
* @tutorial https://uniapp.dcloud.net.cn/api/system/wifi.html#connectWifi
* @uniPlatform {
* "app": {
* "android": {
* "osVer": ">=4.4 && <10.0",
* "uniVer": "3.7.0",
* "unixVer": "3.9.0"
* },
* "ios": {
* "osVer": "9.0",
* "uniVer": "3.7.7",
* "unixVer": "3.9.0"
* }
* }
* }
* @uniVersion 3.7.7
* @uniVueVersion 2,3 //支持的vue版本
* @autotest {
generated: false,
pollution: false,
cases:[
{
before: 'startWifi',
after: 'stopWifi',
input: [{
maunal:false,
SSID:"Xiaomi_20D0",
password:"streamApp!2016",
}],
output:{
callbackType: 'success',
value: { errCode: 12013 ,errMsg: "connectWifi:wifi config may be expired",errSubject: "uni-connectWifi"}
}
}
]
}
*/
connectWifi(option : UniNamespace.WifiConnectOption) : void,
/**
* 请求获取 Wi-Fi 列表。wifiList 数据会在 onGetWifiList 注册的回调中返回。
* @param {WifiOption} option
* @tutorial https://uniapp.dcloud.net.cn/api/system/wifi.html#getWifiList
* @uniPlatform {
* "app": {
* "android": {
* "osVer": "4.4.4",
* "uniVer": "3.7.0",
* "unixVer": "3.9.0"
* },
* "ios": {
* "osVer": "9.0",
* "uniVer": "3.7.7",
* "unixVer": "3.9.0"
* }
* }
* }
* @uniVersion 3.7.7
* @uniVueVersion 2,3 //支持的vue版本
* @autotest { before: 'startWifi', after: 'stopWifi' }
*/
getWifiList(option : UniNamespace.WifiOption) : void,
/**
* 监听获取到 Wi-Fi 列表数据事件。
*
* @param {UniWifiCallback} callback
* @tutorial https://uniapp.dcloud.net.cn/api/system/wifi.html#onGetWifiList
* @uniPlatform {
* "app": {
* "android": {
* "osVer": "4.4.4",
* "uniVer": "3.7.0",
* "unixVer": "3.9.0"
* },
* "ios": {
* "osVer": "9.0",
* "uniVer": "3.7.7",
* "unixVer": "3.9.0"
* }
* }
* }
* @uniVersion 3.7.7
* @uniVueVersion 2,3 //支持的vue版本
* @autotest { expectCallback: true }
* @autotest {
generated: false,
pollution: false,
expectCallback: true,
before: 'startWifi',
after: 'onGetWifiListAfter',
cases: [
{
output: {
value: 0,
returnKey: '.wifiList.length',
jestExpectSyntax: 'toBeGreaterThan'
},
}
]
}
*/
onGetWifiList(callback : UniNamespace.UniGetWifiListCallback) : void,
/**
* 移除获取到 Wi-Fi 列表数据事件的监听函数。
*
* @param {UniWifiCallback} callback
* @tutorial https://uniapp.dcloud.net.cn/api/system/wifi.html#offGetWifiList
* @uniPlatform {
* "app": {
* "android": {
* "osVer": "4.4.4",
* "uniVer": "3.7.0",
* "unixVer": "3.9.0"
* },
* "ios": {
* "osVer": "9.0",
* "uniVer": "3.7.7",
* "unixVer": "3.9.0"
* }
* }
* }
* @uniVersion 3.7.7
* @uniVueVersion 2,3 //支持的vue版本
* @autotest { expectCallback: true }
*/
offGetWifiList(callback : UniNamespace.UniWifiCallback) : void,
/**
* 获取已连接的 Wi-Fi 信息
*
* @param {GetConnectedWifiOptions} option
* @tutorial https://uniapp.dcloud.net.cn/api/system/wifi.html#getConnectedWifi
* @uniPlatform {
* "app": {
* "android": {
* "osVer": "4.4.4",
* "uniVer": "3.7.0",
* "unixVer": "3.9.0"
* },
* "ios": {
* "osVer": "9.0",
* "uniVer": "3.7.7",
* "unixVer": "3.9.0"
* }
* }
* }
* @uniVersion 3.7.7
* @uniVueVersion 2,3 //支持的vue版本
* @autotest { before: 'startWifi', after: 'stopWifi' }
*/
getConnectedWifi(option : UniNamespace.GetConnectedWifiOptions) : void,
/**
* 监听连接上 Wi-Fi 的事件
*
* @param {UniWifiCallback} callback
* @tutorial https://uniapp.dcloud.net.cn/api/system/wifi.html#onWifiConnected
* @uniPlatform {
* "app": {
* "android": {
* "osVer": "4.4.4",
* "uniVer": "3.7.0",
* "unixVer": "3.9.0"
* },
* "ios": {
* "osVer": "9.0",
* "uniVer": "3.7.7",
* "unixVer": "3.9.0"
* }
* }
* }
* @uniVersion 3.7.7
* @uniVueVersion 2,3 //支持的vue版本
* @autotest { expectCallback: true }
*/
onWifiConnected(callback : UniNamespace.UniWifiResultCallback) : void,
/**
* 监听连接上 Wi-Fi 的事件。
*
* @param {UniWifiCallback} callback
* @tutorial https://uniapp.dcloud.net.cn/api/system/wifi.html#onWifiConnectedWithPartialInfo
* @uniPlatform {
* "app": {
* "android": {
* "osVer": "4.4.4",
* "uniVer": "3.7.0",
* "unixVer": "3.9.0"
* },
* "ios": {
* "osVer": "9.0",
* "uniVer": "3.7.7",
* "unixVer": "3.9.0"
* }
* }
* }
* @uniVersion 3.7.7
* @uniVueVersion 2,3 //支持的vue版本
* @autotest { expectCallback: true }
*/
onWifiConnectedWithPartialInfo(callback : UniNamespace.UniWifiResultCallbackWithPartialInfo) : void,
/**
* 移除连接上 Wi-Fi 的事件的监听函数。
*
* @param {UniWifiCallback} callback
* @tutorial https://uniapp.dcloud.net.cn/api/system/wifi.html#offWifiConnected
* @uniPlatform {
* "app": {
* "android": {
* "osVer": "4.4.4",
* "uniVer": "3.7.0",
* "unixVer": "3.9.0"
* },
* "ios": {
* "osVer": "9.0",
* "uniVer": "3.7.7",
* "unixVer": "3.9.0"
* }
* }
* }
* @uniVersion 3.7.7
* @uniVueVersion 2,3 //支持的vue版本
* @autotest { expectCallback: true }
*/
offWifiConnected(callback ?: UniNamespace.UniWifiCallback) : void,
/**
* 移除连接上 Wi-Fi 的事件的监听函数。
*
* @param {UniWifiCallback} callback
* @tutorial https://uniapp.dcloud.net.cn/api/system/wifi.html#offWifiConnectedWithPartialInfo
* @uniPlatform {
* "app": {
* "android": {
* "osVer": "x",
* "uniVer": "x",
* "unixVer": "x"
* },
* "ios": {
* "osVer": "x",
* "uniVer": "x",
* "unixVer": "x"
* }
* }
* }
* @uniVersion 3.7.7
* @uniVueVersion 2,3 //支持的vue版本
* @autotest { expectCallback: true }
*/
offWifiConnectedWithPartialInfo(callback ?: UniNamespace.UniWifiResultCallbackWithPartialInfo) : void,
/**
* SetWifiList 暂未实现
*
* @uniPlatform {
* "app": {
* "android": {
* "osVer": "x",
* "uniVer": "x",
* "unixVer": "x"
* },
* "ios": {
* "osVer": "x",
* "uniVer": "x",
* "unixVer": "x"
* }
* }
* }
*/
setWifiList(option : UniNamespace.WifiOption) : void,
}
......@@ -42,6 +42,10 @@ export type UniWifiInfo = {
frequency ?: number;
}
export type UniWifiInfoWithPartialInfo = {
SSID : string;
}
export type UniWifiResult = {
errCode : number,
......@@ -52,6 +56,12 @@ export type UniWifiResult = {
export type UniWifiCallback = () => void
export type UniGetWifiListCallback = (wifiInfo:UTSJSONObject) => void
export type UniWifiResultCallback = (wifiInfo:UniWifiResult) => void
export type UniWifiResultCallbackWithPartialInfo = (wifiInfo:UniWifiInfoWithPartialInfo) => void
export type StartWifi = (option : WifiOption) => void
......@@ -59,7 +69,7 @@ export type StopWifi = (option : WifiOption) => void
export type GetWifiList = (option : WifiOption) => void
export type OnGetWifiList = (callback : UniWifiCallback) => void
export type OnGetWifiList = (callback : UniGetWifiListCallback) => void
export type OffGetWifiList = (callback : UniWifiCallback) => void
......@@ -67,16 +77,35 @@ export type GetConnectedWifi = (option : GetConnectedWifiOptions) => void
export type ConnectWifi = (option : WifiConnectOption) => void
export type OnWifiConnected = (callback : UniWifiCallback) => void
export type OnWifiConnected = (callback : UniWifiResultCallback) => void
export type OnWifiConnectedWithPartialInfo = (callback : UniWifiCallback) => void
export type OnWifiConnectedWithPartialInfo = (callback : UniWifiResultCallbackWithPartialInfo) => void
export type OffWifiConnected = (callback : UniWifiCallback | null) => void
export type OnOffWifiConnectedWithPartialInfo = (callback : UniWifiCallback | null) => void
export type OffWifiConnectedWithPartialInfo = (callback : UniWifiResultCallbackWithPartialInfo | null) => void
export type SetWifiList = (option : WifiOption) => void
/**
* 错误码
* - 12000 尚未初始化
* - 12001 当前系统不支持相关能力
* - 12002 密码错误
* - 12005 Android 特有,未打开 Wi-Fi 开关
* - 12007 用户拒绝授权链接 Wi-Fi
* - 12010 系统其他错误
* - 12013 系统保存的 Wi-Fi 配置过期,建议忘记 Wi-Fi 后重试,仅 Android 支持
*/
export type WifiErrorCode = 12000 |12001 | 12002 | 12005 | 12007 | 12010 | 12013;
export interface WifiFail extends IUniError{
errCode: WifiErrorCode
};
interface Uni {
/**
* 初始化Wi-Fi模块
......@@ -228,7 +257,7 @@ interface Uni {
]
}
*/
onGetWifiList(callback : UniWifiCallback) : void,
onGetWifiList(callback : UniGetWifiListCallback) : void,
/**
* 移除获取到 Wi-Fi 列表数据事件的监听函数。
*
......@@ -300,7 +329,7 @@ interface Uni {
* @uniVueVersion 2,3 //支持的vue版本
* @autotest { expectCallback: true }
*/
onWifiConnected(callback : UniWifiCallback) : void,
onWifiConnected(callback : UniWifiResultCallback) : void,
/**
* 监听连接上 Wi-Fi 的事件。
*
......@@ -324,7 +353,7 @@ interface Uni {
* @uniVueVersion 2,3 //支持的vue版本
* @autotest { expectCallback: true }
*/
onWifiConnectedWithPartialInfo(callback : UniWifiCallback) : void,
onWifiConnectedWithPartialInfo(callback : UniWifiResultCallbackWithPartialInfo) : void,
/**
* 移除连接上 Wi-Fi 的事件的监听函数。
*
......@@ -353,7 +382,7 @@ interface Uni {
* 移除连接上 Wi-Fi 的事件的监听函数。
*
* @param {UniWifiCallback} callback
* @tutorial https://uniapp.dcloud.net.cn/api/system/wifi.html#onOffWifiConnectedWithPartialInfo
* @tutorial https://uniapp.dcloud.net.cn/api/system/wifi.html#offWifiConnectedWithPartialInfo
* @uniPlatform {
* "app": {
* "android": {
......@@ -372,7 +401,7 @@ interface Uni {
* @uniVueVersion 2,3 //支持的vue版本
* @autotest { expectCallback: true }
*/
onOffWifiConnectedWithPartialInfo(callback : UniWifiCallback | null) : void,
offWifiConnectedWithPartialInfo(callback : UniWifiResultCallbackWithPartialInfo | null) : void,
/**
* SetWifiList 暂未实现
*
......
import { WifiErrorCode, WifiFail} from "./interface.uts"
/**
* 错误主题
*/
export const UniErrorSubject = 'uni-wifi';
/**
* 错误码
* @UniError
*/
export const WifiUniErrors : Map<WifiErrorCode, string> = new Map([
/**
* 未先调用 startWifi 接口
*/
[12000, 'not init.'],
/**
* 当前系统不支持相关能力
*/
[12001, 'system not support'],
/**
* 密码错误
*/
[12002, 'password error Wi-Fi'],
/**
* Android 特有,未打开 Wi-Fi 开关
*/
[12005, 'wifi not turned on'],
/**
* 用户拒绝授权链接 Wi-Fi
*/
[12007, 'user denied'],
/**
* 系统其他错误,需要在 errmsg 打印具体的错误原因
*/
[12010, 'unknown error'],
/**
* 系统保存的 Wi-Fi 配置过期,建议忘记 Wi-Fi 后重试,仅 Android 支持
*/
[12013, 'wifi config may be expired'],
]);
export function getErrcode(errCode : number) : WifiErrorCode {
const res = WifiUniErrors[errCode];
return res == null ? 12000 : errCode;
}
export class WifiFailImpl extends UniError implements WifiFail {
constructor(errCode : WifiErrorCode) {
super();
this.errSubject = UniErrorSubject;
this.errCode = errCode;
this.errMsg = WifiUniErrors[errCode] ?? "";
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册