提交 630014b6 编写于 作者: DCloud_iOS_WZT's avatar DCloud_iOS_WZT

Merge branch 'alpha' of https://gitcode.net/dcloud/uni-api into alpha

root = true
[*]
charset = utf-8
end_of_line = lf
indent_style = space
indent_size = 2
trim_trailing_whitespace = true
insert_final_newline = true
......@@ -2,3 +2,14 @@
/.hbuilderx
/.vite
.DS_Store
<<<<<<< HEAD
=======
>>>>>>> dev
env.js
jest.config.js
autotest.reporter.js
autotest.utils.js
pages/autotest/
node_modules/
vite.config.js
\ No newline at end of file
......@@ -14,8 +14,9 @@
},
{
"bundleId" : "io.dcloud.test123456",
"certificateFile" : "/Users/lizhongyi/Desktop/文件/证书/dev_123.p12",
"certificateProfileFile" : "/Users/lizhongyi/Desktop/文件/证书/io_dcloud_test123456.mobileprovision",
"certificateFile" : "/Users/lizhongyi/Desktop/newProfiles/dev_123.p12",
"certificateProfileFile" : "/Users/lizhongyi/Desktop/newProfiles/wildcard.mobileprovision",
"runSignStatus" : 1,
"type" : "uni-app:app-ios"
}
]
......
<script lang="uts">
let firstBackTime = 0
export default {
onLaunch: function () {
console.log('App Launch')
},
onShow: function () {
console.log('App Show')
},
onHide: function () {
console.log('App Hide')
},
onLastPageBackPress: function () {
console.log('App LastPageBackPress')
if (firstBackTime == 0) {
uni.showToast({
title: '再按一次退出应用',
position: 'bottom',
})
firstBackTime = Date.now()
setTimeout(() => {
firstBackTime = 0
}, 2000)
} else if (Date.now() - firstBackTime < 2000) {
firstBackTime = Date.now()
uni.exit()
}
},
onExit: function () {
console.log('App Exit')
},
}
</script>
<style>
/*每个页面公共css */
.uni-row {
flex-direction: row;
}
.uni-column {
flex-direction: column;
}
</style>
\ No newline at end of file
module.exports = {
testTimeout: 10000,
reporters: [
'default'
],
watchPathIgnorePatterns: ['/node_modules/', '/dist/', '/.git/'],
moduleFileExtensions: ['js', 'json'],
rootDir: __dirname,
testMatch: ["<rootDir>/pages/**/*test.[jt]s?(x)"],
testPathIgnorePatterns: ['/node_modules/']
}
import App from './App'
import { createSSRApp } from 'vue'
export function createApp() {
const app = createSSRApp(App)
return {
app
}
}
\ No newline at end of file
{
"name": "uni-api",
"appid": "__UNI__ED9218B",
"description": "",
"appid": "__UNI__8BF79AC",
"description": "uts插件示例",
"versionName": "1.0.0",
"versionCode": "100",
"transformPx": false,
/* 5+App特有相关 */
/* uni-app x 特有相关 */
// "uni-app-x": {},
/* uni-app特有相关 */
"app-plus": {
"usingComponents": true,
"nvueStyleCompiler": "uni-app",
......@@ -21,25 +23,7 @@
/* 应用发布信息 */
"distribute": {
/* android打包配置 */
"android": {
"permissions": [
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
"<uses-feature android:name=\"android.hardware.camera\"/>",
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
]
},
"android": {},
/* ios打包配置 */
"ios": {},
/* SDK配置 */
......@@ -68,5 +52,5 @@
"uniStatistics": {
"enable": false
},
"vueVersion": "2"
"vueVersion": "3"
}
......@@ -3,7 +3,14 @@
{
"path": "pages/index/index",
"style": {
"navigationBarTitleText": "uni-app"
"navigationBarTitleText": "uni-api"
}
},
{
"path": "pages/test/test",
"style": {
"navigationBarTitleText": "测试示例",
"enablePullDownRefresh": false
}
}
],
......
<template>
<!-- #ifdef APP -->
<scroll-view class="content">
<!-- #endif -->
<image class="logo" src="/static/logo.png"></image>
<view class="text-area">
<text class="title">{{title}}</text>
</view>
<view class="buttons">
<button class="button" @tap="openTest" type="primary">测试示例</button>
</view>
<!-- #ifdef APP -->
</scroll-view>
<!-- #endif -->
</template>
<script>
export default {
data() {
return {
title: 'Hello'
}
},
methods: {
openTest() {
uni.navigateTo({
url: '/pages/test/test'
})
}
}
}
</script>
<style>
.content {
display: flex;
flex: 1;
align-items: center;
}
.logo {
height: 200rpx;
width: 200rpx;
margin-top: 200rpx;
margin-bottom: 50rpx;
}
.title {
font-size: 36rpx;
color: #8f8f94;
}
.buttons {
margin-top: 50px;
margin-bottom: 50px;
}
.button {
width: 640rpx;
margin: 10px;
}
</style>
\ No newline at end of file
<template>
<!-- #ifdef APP -->
<scroll-view class="content">
<!-- #endif -->
<image class="logo" src="/static/logo.png"></image>
<view class="text-area">
<text class="title">{{title}}</text>
</view>
<view class="buttons">
<button class="button" @tap="openTest" type="primary">测试示例</button>
</view>
<!-- #ifdef APP -->
</scroll-view>
<!-- #endif -->
</template>
<script>
export default {
data() {
return {
title: 'Hello'
}
},
methods: {
openTest() {
uni.navigateTo({
url: '/pages/test/test'
})
}
}
}
</script>
<style>
.content {
display: flex;
flex: 1;
align-items: center;
}
.logo {
height: 200rpx;
width: 200rpx;
margin-top: 200rpx;
margin-bottom: 50rpx;
}
.title {
font-size: 36rpx;
color: #8f8f94;
}
.buttons {
margin-top: 50px;
margin-bottom: 50px;
}
.button {
width: 640rpx;
margin: 10px;
}
</style>
\ No newline at end of file
<template>
<!-- #ifdef APP -->
<scroll-view class="content">
<!-- #endif -->
<!-- #ifdef APP -->
</scroll-view>
<!-- #endif -->
</template>
<script>
export default {
data() {
return {
}
},
methods: {
}
}
</script>
<style>
.content {
display: flex;
flex: 1;
align-items: center;
}
</style>
\ No newline at end of file
......@@ -16,37 +16,64 @@
<button @tap="testSetUserCaptureScreen">{{setUserCaptureScreenText}}</button>
<button @tap="testGetBatteryInfo">获取电池电量</button>
<button @tap="testGetBatteryInfoSync">同步获取电池电量</button>
<button @tap="testonMemoryWarning">开启内存不足告警监听</button>
<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>
<script>
import {
installApk
} from "@/uni_modules/uni-installApk"
let pre = 0
let speed = 1
let preTime = 0
let isBegin = false
export default {
data() {
return {
memListener:null,
memListener: null,
setUserCaptureScreenFlag: false,
setUserCaptureScreenText: '禁止截屏',
permissionGranted: false
permissionGranted: false,
id: 0
}
},
onLoad() {
},
methods: {
onMemoryWarning:function(res){
onMemoryWarning: function(res) {
console.log(res);
},
fn:function(res){
fn: function(res) {
console.log(res)
},
getLocationTest() {
console.log(" ------- getLocationTest: ");
uni.getLocation({
type: 'gcj02 ',
success(res) {
console.log(" success ", res);
},
fail(res) {
console.log(" fail ", res);
}
})
},
onGetWifiList2_assert0() {
console.log(" ------- onGetWifiList2_assert0: ", this.id);
const fn = res => console.log('onGetWifiList res', res)
uni.startWifi({success(){
uni.startWifi({
success() {
uni.onGetWifiList(fn)
uni.getWifiList({
success() {
......@@ -55,18 +82,20 @@
uni.stopWifi({
success() {},
fail(e) {
console.log("stopWifi fail: ",e);
console.log("stopWifi fail: ", e);
}
})
}
})
}
})
}})
this.id++
},
testConnnectWifi(){
testConnnectWifi() {
uni.startWifi({
success:(res)=> {
success: (res) => {
console.log("success: " + JSON.stringify(res));
// uni.connectWifi({
// maunal:false,
......@@ -76,9 +105,11 @@
// console.log(res);
// }
// });
},fail:(res)=>{
},
fail: (res) => {
console.log("fail: " + JSON.stringify(res));
},complete:(res)=>{
},
complete: (res) => {
console.log("complete: " + JSON.stringify(res));
}
})
......@@ -86,47 +117,49 @@
},
testGetConnnectWifi(){
testGetConnnectWifi() {
uni.getConnectedWifi({
partialInfo:false,
complete:(res)=>{
partialInfo: false,
complete: (res) => {
console.log(res);
if (res.errCode == 0) {
uni.showToast({
icon:'none',
title:res.wifi.SSID
icon: 'none',
title: res.wifi.SSID
})
} else{
} else {
uni.showToast({
icon:'none',
title:res.errMsg
icon: 'none',
title: res.errMsg
})
}
}
});
},
testStartWifi(){
testStartWifi() {
uni.startWifi({
success:(res)=> {
success: (res) => {
console.log("success: " + JSON.stringify(res));
// wifi 开启成功后,注册wifi链接状态监听和wifi列表获取监听
uni.onGetWifiList(function(res){
uni.onGetWifiList(function(res) {
console.log("onGetWifiList");
console.log(res);
});
uni.onWifiConnected(function(res){
uni.onWifiConnected(function(res) {
console.log("onWifiConnected");
console.log(res);
});
uni.onWifiConnectedWithPartialInfo(function(res){
uni.onWifiConnectedWithPartialInfo(function(res) {
console.log("onWifiConnectedWithPartialInfo");
console.log(res);
});
},fail:(res)=>{
},
fail: (res) => {
console.log("fail: " + JSON.stringify(res));
},complete:(res)=>{
},
complete: (res) => {
console.log("complete: " + JSON.stringify(res));
}
})
......@@ -136,11 +169,13 @@
uni.offWifiConnectedWithPartialInfo()
uni.stopWifi({
success:(res)=> {
success: (res) => {
console.log("success: " + JSON.stringify(res));
},fail:(res)=>{
},
fail: (res) => {
console.log("fail: " + JSON.stringify(res));
},complete:(res)=>{
},
complete: (res) => {
console.log("complete: " + JSON.stringify(res));
}
})
......@@ -148,18 +183,20 @@
},
testGetWifiList() {
uni.getWifiList({
success:(res)=> {
success: (res) => {
console.log("success: " + JSON.stringify(res));
},fail:(res)=>{
},
fail: (res) => {
console.log("fail: " + JSON.stringify(res));
},complete:(res)=>{
},
complete: (res) => {
console.log("complete: " + JSON.stringify(res));
}
})
},
testOffGetWifiList(){
testOffGetWifiList() {
uni.offGetWifiList()
},
......@@ -168,15 +205,15 @@
testonMemoryWarning() {
uni.onMemoryWarning(this.onMemoryWarning)
uni.showToast({
icon:'none',
title:'已监听,注意控制台输出'
icon: 'none',
title: '已监听,注意控制台输出'
})
},
testoffMemoryWarning(){
testoffMemoryWarning() {
uni.offMemoryWarning(this.onMemoryWarning)
uni.showToast({
icon:'none',
title:'监听已移除'
icon: 'none',
title: '监听已移除'
})
},
testScreenShotListen() {
......@@ -184,8 +221,8 @@
uni.onUserCaptureScreen(function(res) {
console.log(res);
uni.showToast({
icon:"none",
title:'捕获截屏事件'
icon: "none",
title: '捕获截屏事件'
})
that.screenImage = res.path
});
......@@ -193,8 +230,8 @@
if (uni.getSystemInfoSync().platform != "android" || that.permissionGranted) {
// 除android 之外的平台,直接提示监听已开启
uni.showToast({
icon:"none",
title:'截屏监听已开启'
icon: "none",
title: '截屏监听已开启'
})
}
},
......@@ -204,8 +241,8 @@
});
// 提示已经开始监听,注意观察
uni.showToast({
icon:"none",
title:'截屏监听已关闭'
icon: "none",
title: '截屏监听已关闭'
})
},
testGetBatteryInfo() {
......@@ -219,22 +256,30 @@
}
})
},
testGetBatteryInfoSync() {
let ret = uni.getBatteryInfoSync()
console.log(ret)
},
testSetUserCaptureScreen() {
let flag = this.setUserCaptureScreenFlag;
uni.setUserCaptureScreen({
enable: flag,
success: (res) => {
console.log("setUserCaptureScreen enable: " + flag + " success: " + JSON.stringify(res));
console.log("setUserCaptureScreen enable: " + flag + " success: " + JSON.stringify(
res));
},
fail: (res) => {
console.log("setUserCaptureScreen enable: " + flag + " fail: " + JSON.stringify(res));
},
complete: (res) => {
console.log("setUserCaptureScreen enable: " + flag + " complete: " + JSON.stringify(res));
console.log("setUserCaptureScreen enable: " + flag + " complete: " + JSON.stringify(
res));
}
});
uni.showToast({
icon:"none",
icon: "none",
title: this.setUserCaptureScreenText
});
this.setUserCaptureScreenFlag = !this.setUserCaptureScreenFlag;
......@@ -244,6 +289,72 @@
this.setUserCaptureScreenText = '禁止截屏';
}
},
handleInstallApk() {
installApk({
// filePath: "/sdcard/Android/data/io.dcloud.HBuilder/apps/HBuilder/doc/ddd.apk",
filePath:"/static/test.apk",
complete(res) {
console.log(res);
}
})
},
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>
......
文件已添加
{
"id": "uni-exit",
"displayName": "uni-exit",
"version": "1.0.0",
"description": "uni-exit",
"keywords": [
"uni-exit"
],
"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": {
"exit": {
"name": "exit",
"app": {
"js": true,
"kotlin": true,
"swift": true
}
}
}
},
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "u",
"aliyun": "u"
},
"client": {
"Vue": {
"vue2": "y",
"vue3": "y"
},
"App": {
"app-android": "y",
"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-quit
### 开发文档
[UTS 语法](https://uniapp.dcloud.net.cn/tutorial/syntax-uts.html)
[UTS API插件](https://uniapp.dcloud.net.cn/plugin/uts-plugin.html)
[UTS 组件插件](https://uniapp.dcloud.net.cn/plugin/uts-component.html)
[Hello UTS](https://gitcode.net/dcloud/hello-uts)
\ No newline at end of file
import { ExitOptions, ExitSuccess, Exit } from "../interface.uts"
/**
* 实现uni.exit
*/
export const exit : Exit = function (options: ExitOptions | null) {
let ret : ExitSuccess ={
errMsg: "exit:ok"
}
options?.success?.(ret)
options?.complete?.(ret)
UTSAndroid.exit()
}
import { ExitOptions, Exit} from "../interface.uts"
import { ExitFailImpl } from "../unierror.uts"
/**
* 实现uni.exit
* iOS平台不支持,触发错误回调
*/
export const exit : Exit = function (options: ExitOptions | null) {
let err = new ExitFailImpl(12001);
options?.fail?.(err)
options?.complete?.(err)
}
/**
* uni.exit成功回调参数
*/
export type ExitSuccess = {
errMsg: string
}
/**
* 错误码
* - 12001: 系统不支持
* - 12002: 未知错误
*/
export type ExitErrorCode = 12001 | 12002
/**
* uni.exit失败回调参数
*/
export interface IExitError extends IUniError {
errCode: ExitErrorCode
}
export type ExitFail = IExitError
/**
* uni.exit成功回调函数定义
*/
export type ExitSuccessCallback = (res: ExitSuccess) => void
/**
* uni.exit失败回调函数定义
*/
export type ExitFailCallback = (res: ExitFail) => void
/**
* uni.exit完成回调函数定义
*/
export type ExitCompleteCallback = (res: any) => void
/**
* uni.exit参数定义
*/
export type ExitOptions = {
/**
* 接口调用成功的回调函数
*/
success?: ExitSuccessCallback | null,
/**
* 接口调用失败的回调函数
*/
fail?: ExitFailCallback | null,
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: ExitCompleteCallback | null
}
export interface Uni {
/**
* 退出当前应用
* @uniPlatform {
* "app": {
* "android": {
* "osVer": "4.4.4",
* "uniVer": "3.8.15",
* "unixVer": "3.9.0"
* },
* "ios": {
* "osVer": "x",
* "uniVer": "x",
* "unixVer": "x"
* }
* }
* }
* @uniVueVersion 2,3 //支持的vue版本
*/
exit(options?: ExitOptions | null):void;
}
export type Exit = (options?: ExitOptions | null) => void;
import { ExitErrorCode, IExitError } from "./interface.uts"
/**
* 错误主题
*/
export const UniErrorSubject = 'uni-exit';
/**
* 错误码
* @UniError
*/
export const UniErrors:Map<number, string> = new Map([
/**
* 系统不支持
*/
[12001, 'system not support'],
/**
* 未知错误
*/
[12002, 'unknown error']
]);
/**
* ExitFail的实现
*/
export class ExitFailImpl extends UniError implements IExitError {
override errCode: ExitErrorCode
constructor (
errCode: ExitErrorCode
) {
super()
this.errSubject = UniErrorSubject
this.errCode = errCode
this.errMsg = UniErrors[errCode] ?? "";
}
}
{
"id": "uni-getAppAuthorizeSetting",
"displayName": "uni-getAppAuthorizeSetting",
"version": "1.0.0",
"description": "uni-getAppAuthorizeSetting",
"keywords": [
"uni-getAppAuthorizeSetting"
],
"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": {
"getAppAuthorizeSetting": {
"name": "getAppAuthorizeSetting",
"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-getAppAuthorizeSetting
### 开发文档
[UTS 语法](https://uniapp.dcloud.net.cn/tutorial/syntax-uts.html)
[UTS API插件](https://uniapp.dcloud.net.cn/plugin/uts-plugin.html)
[UTS 组件插件](https://uniapp.dcloud.net.cn/plugin/uts-component.html)
[Hello UTS](https://gitcode.net/dcloud/hello-uts)
\ No newline at end of file
import { GetAppAuthorizeSetting, GetAppAuthorizeSettingResult } from "../interface.uts";
import UTSAndroid from 'io.dcloud.uts.UTSAndroid';
import PackageManager from 'android.content.pm.PackageManager';
import Manifest from 'android.Manifest';
import NotificationManagerCompat from 'androidx.core.app.NotificationManagerCompat';
export const getAppAuthorizeSetting : GetAppAuthorizeSetting = function () : GetAppAuthorizeSettingResult {
const context = UTSAndroid.getUniActivity()!!;
const cameraPermission = [Manifest.permission.CAMERA];
const cameraGranted = UTSAndroid.checkSystemPermissionGranted(context, cameraPermission);
let cameraResult = cameraGranted ? "authorized" : "denied";
if (!cameraGranted && !hasDefinedInManifest(Manifest.permission.CAMERA)) {
cameraResult = "config error";
}
const locationPermission = [Manifest.permission.ACCESS_COARSE_LOCATION];
const coarseLocationGranted = UTSAndroid.checkSystemPermissionGranted(context, locationPermission);
let coarseLocationResult = coarseLocationGranted ? "authorized" : "denied";
if (!coarseLocationGranted && !hasDefinedInManifest(Manifest.permission.ACCESS_COARSE_LOCATION)) {
coarseLocationResult = "config error";
}
const fineLocationPermission = [Manifest.permission.ACCESS_FINE_LOCATION];
const fineLocationGranted = UTSAndroid.checkSystemPermissionGranted(context, fineLocationPermission);
let accuracy = coarseLocationGranted ? "reduced" : "unsupported";
if (coarseLocationGranted && fineLocationGranted) {
accuracy = "full";
}
const recordAudioPermission = [Manifest.permission.RECORD_AUDIO];
const recordAudioGranted = UTSAndroid.checkSystemPermissionGranted(context, recordAudioPermission);
let recordAudioResult = recordAudioGranted ? "authorized" : "denied";
if (!recordAudioGranted && !hasDefinedInManifest(Manifest.permission.RECORD_AUDIO)) {
recordAudioResult = "config error";
}
const compat = NotificationManagerCompat.from(context);
const notificationResult = compat.areNotificationsEnabled() ? "authorized": "denied"
let result : GetAppAuthorizeSettingResult = {
cameraAuthorized: cameraResult,
locationAuthorized: coarseLocationResult,
locationAccuracy: accuracy,
microphoneAuthorized: recordAudioResult,
notificationAuthorized: notificationResult,
albumAuthorized: null,
bluetoothAuthorized: null,
locationReducedAccuracy: null,
notificationAlertAuthorized: null,
notificationBadgeAuthorized: null,
notificationSoundAuthorized: null,
phoneCalendarAuthorized: null
}
return result
};
const hasDefinedInManifest = function (permission : string) : boolean {
try {
const context = UTSAndroid.getAppContext()!!;
const packageInfo = context.getPackageManager().getPackageInfo(context.getApplicationInfo().packageName, PackageManager.GET_PERMISSIONS);
if (packageInfo != null) {
for (const requestPermission in packageInfo.requestedPermissions) {
if (permission == requestPermission) {
return true;
}
}
}
} catch (e : Exception) {
return false
}
return false;
}
\ No newline at end of file
export interface Uni {
/**
* getAppAuthorizeSetting()
* @description
* 获取 APP 授权设置。
* @param {void}
* @return {GetAppAuthorizeSettingResult}
* @tutorial http://uniapp.dcloud.io/api/system/getappauthorizesetting
* @uniPlatform {
* "app": {
* "android": {
* "osVer": "4.4",
* "uniVer": "√",
* "unixVer": "3.9+"
* },
* "ios": {
* "osVer": "9.0",
* "uniVer": "√",
* "unixVer": "x"
* }
* }
* }
* @example
```typescript
uni.getAppAuthorizeSetting()
```
*/
getAppAuthorizeSetting(): GetAppAuthorizeSettingResult;
}
export type GetAppAuthorizeSetting = () => GetAppAuthorizeSettingResult;
export type GetAppAuthorizeSettingResult = {
/**
* 允许 App 使用相册的开关(仅 iOS 支持)
* - authorized: 已经获得授权,无需再次请求授权
* - denied: 请求授权被拒绝,无法再次请求授权;(此情况需要引导用户打开系统设置,在设置页中打开权限)
* - not determined: 尚未请求授权,会在App下一次调用系统相应权限时请求;(仅 iOS 会出现。此种情况下引导用户打开系统设置,不展示开关)
* @type 'authorized' | 'denied' | 'not determined'
* @uniPlatform {
* "app": {
* "android": {
* "osVer": "x",
* "uniVer": "x",
* "unixVer": "x"
* },
* "ios": {
* "osVer": "9.0",
* "uniVer": "√",
* "unixVer": "x"
* }
* }
* }
*/
albumAuthorized: string | null,
/**
* 允许 App 使用蓝牙的开关(仅 iOS 支持)
* - authorized: 已经获得授权,无需再次请求授权
* - denied: 请求授权被拒绝,无法再次请求授权;(此情况需要引导用户打开系统设置,在设置页中打开权限)
* - not determined: 尚未请求授权,会在App下一次调用系统相应权限时请求;(仅 iOS 会出现。此种情况下引导用户打开系统设置,不展示开关)
* - config error: Android平台没有该值;iOS平台:表示没有在 `manifest.json -> App模块配置` 中配置 `BlueTooth(低功耗蓝牙)` 模块
* @type 'authorized' | 'denied' | 'not determined' | 'config error'
* @uniPlatform {
* "app": {
* "android": {
* "osVer": "x",
* "uniVer": "x",
* "unixVer": "x"
* },
* "ios": {
* "osVer": "9.0",
* "uniVer": "√",
* "unixVer": "x"
* }
* }
* }
*/
bluetoothAuthorized: string | null,
/**
* 允许 App 使用摄像头的开关
* - authorized: 已经获得授权,无需再次请求授权
* - denied: 请求授权被拒绝,无法再次请求授权;(此情况需要引导用户打开系统设置,在设置页中打开权限)
* - not determined: 尚未请求授权,会在App下一次调用系统相应权限时请求;(仅 iOS 会出现。此种情况下引导用户打开系统设置,不展示开关)
* - config error: Android平台:表示没有授予 `android.permission.CAMERA` 权限;iOS平台没有该值
* @type 'authorized' | 'denied' | 'not determined' | 'config error'
*/
cameraAuthorized: string,
/**
* 允许 App 使用定位的开关
* - authorized: 已经获得授权,无需再次请求授权
* - denied: 请求授权被拒绝,无法再次请求授权;(此情况需要引导用户打开系统设置,在设置页中打开权限)
* - not determined: 尚未请求授权,会在App下一次调用系统相应权限时请求;(仅 iOS 会出现。此种情况下引导用户打开系统设置,不展示开关)
* - config error: Android平台:表示没有授予 `android.permission.ACCESS_COARSE_LOCATION` 权限;iOS平台:表示没有在 `manifest.json -> App模块配置` 中配置 `Geolocation(定位)` 模块
* @type 'authorized' | 'denied' | 'not determined' | 'config error'
*/
locationAuthorized: string,
/**
* 定位准确度。true 表示模糊定位,false 表示精确定位
* - reduced: 模糊定位
* - full: 精准定位
* - unsupported: 不支持(包括用户拒绝定位权限和没有在 `manifest.json -> App模块配置` 中配置 `Geolocation(定位)` 模块)
* @type 'reduced' | 'full' | 'unsupported'
*/
locationAccuracy: string | null,
/**
* 定位准确度(推荐使用 locationAccuracy 属性)。true 表示模糊定位,false 表示精确定位(仅 iOS 支持)
* @type boolean
* @uniPlatform {
* "app": {
* "android": {
* "osVer": "x",
* "uniVer": "x",
* "unixVer": "x"
* },
* "ios": {
* "osVer": "9.0",
* "uniVer": "√",
* "unixVer": "x"
* }
* }
* }
*/
locationReducedAccuracy: boolean | null,
/**
* 允许 App 使用麦克风的开关
* - authorized: 已经获得授权,无需再次请求授权
* - denied: 请求授权被拒绝,无法再次请求授权;(此情况需要引导用户打开系统设置,在设置页中打开权限)
* - not determined: 尚未请求授权,会在App下一次调用系统相应权限时请求;(仅 iOS 会出现。此种情况下引导用户打开系统设置,不展示开关)
* - config error: Android平台:表示没有授予 `android.permission.RECORD_AUDIO` 权限;iOS平台没有该值
* @type 'authorized' | 'denied' | 'not determined' | 'config error'
*/
microphoneAuthorized: string,
/**
* 允许 App 通知的开关
* - authorized: 已经获得授权,无需再次请求授权
* - denied: 请求授权被拒绝,无法再次请求授权;(此情况需要引导用户打开系统设置,在设置页中打开权限)
* - not determined: 尚未请求授权,会在App下一次调用系统相应权限时请求;(仅 iOS 会出现。此种情况下引导用户打开系统设置,不展示开关)
* - config error: Android平台没有该值;iOS平台:表示没有在 `manifest.json -> App模块配置` 中配置 `Push(推送)` 模块
* @type 'authorized' | 'denied' | 'not determined' | 'config error'
*/
notificationAuthorized: string,
/**
* 允许 App 通知带有提醒的开关(仅 iOS 10.0+ 支持)
* - authorized: 已经获得授权,无需再次请求授权
* - denied: 请求授权被拒绝,无法再次请求授权;(此情况需要引导用户打开系统设置,在设置页中打开权限)
* - not determined: 尚未请求授权,会在App下一次调用系统相应权限时请求;(仅 iOS 会出现。此种情况下引导用户打开系统设置,不展示开关)
* - config error: 没有在 `manifest.json -> App模块配置` 中配置 `Push(推送)` 模块
* @type 'authorized' | 'denied' | 'not determined' | 'config error'
* @uniPlatform {
* "app": {
* "android": {
* "osVer": "x",
* "uniVer": "x",
* "unixVer": "x"
* },
* "ios": {
* "osVer": "10.0",
* "uniVer": "√",
* "unixVer": "x"
* }
* }
* }
*/
notificationAlertAuthorized: string | null,
/**
* 允许 App 通知带有标记的开关(仅 iOS 10.0+ 支持)
* - authorized: 已经获得授权,无需再次请求授权
* - denied: 请求授权被拒绝,无法再次请求授权;(此情况需要引导用户打开系统设置,在设置页中打开权限)
* - not determined: 尚未请求授权,会在App下一次调用系统相应权限时请求;(仅 iOS 会出现。此种情况下引导用户打开系统设置,不展示开关)
* - config error: 没有在 `manifest.json -> App模块配置` 中配置 `Push(推送)` 模块
* @type 'authorized' | 'denied' | 'not determined' | 'config error'
* @uniPlatform {
* "app": {
* "android": {
* "osVer": "x",
* "uniVer": "x",
* "unixVer": "x"
* },
* "ios": {
* "osVer": "10.0",
* "uniVer": "√",
* "unixVer": "x"
* }
* }
* }
*/
notificationBadgeAuthorized: string | null,
/**
* 允许 App 通知带有声音的开关(仅 iOS 10.0+ 支持)
* - authorized: 已经获得授权,无需再次请求授权
* - denied: 请求授权被拒绝,无法再次请求授权;(此情况需要引导用户打开系统设置,在设置页中打开权限)
* - not determined: 尚未请求授权,会在App下一次调用系统相应权限时请求;(仅 iOS 会出现。此种情况下引导用户打开系统设置,不展示开关)
* - config error: 没有在 `manifest.json -> App模块配置` 中配置 `Push(推送)` 模块
* @type 'authorized' | 'denied' | 'not determined' | 'config error'
* @uniPlatform {
* "app": {
* "android": {
* "osVer": "x",
* "uniVer": "x",
* "unixVer": "x"
* },
* "ios": {
* "osVer": "10.0",
* "uniVer": "√",
* "unixVer": "x"
* }
* }
* }
*/
notificationSoundAuthorized: string | null,
/**
* 允许读写日历的开关(仅微信小程序支持)
* - authorized: 已经获得授权,无需再次请求授权
* - denied: 请求授权被拒绝,无法再次请求授权;(此情况需要引导用户打开系统设置,在设置页中打开权限)
* - not determined: 尚未请求授权,会在App下一次调用系统相应权限时请求;(仅 iOS 会出现。此种情况下引导用户打开系统设置,不展示开关)
* @type 'authorized' | 'denied' | 'not determined'
* @uniPlatform {
* "app": {
* "android": {
* "osVer": "x",
* "uniVer": "x",
* "unixVer": "x"
* },
* "ios": {
* "osVer": "x",
* "uniVer": "x",
* "unixVer": "x"
* }
* }
* }
*/
phoneCalendarAuthorized: string | null
};
{
"id": "uni-getAppBaseInfo",
"displayName": "uni-getAppBaseInfo",
"version": "1.0.0",
"description": "uni-getAppBaseInfo",
"keywords": [
"uni-getAppBaseInfo"
],
"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": {
"getAppBaseInfo": {
"name": "getAppBaseInfo",
"app": {
"js": false,
"kotlin": true,
"swift": true
}
}
}
},
"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-getAppBaseInfo
### 开发文档
[UTS 语法](https://uniapp.dcloud.net.cn/tutorial/syntax-uts.html)
[UTS 原生插件](https://uniapp.dcloud.net.cn/plugin/uts-plugin.html)
[Hello UTS](https://gitcode.net/dcloud/hello-uts/-/tree/dev)
\ No newline at end of file
import { UTSAndroid as Device} from "io.dcloud.uts";
import PackageManager from 'android.content.pm.PackageManager';
import Context from 'android.content.Context';
import PackageInfo from 'android.content.pm.PackageInfo';
import UiModeManager from 'android.app.UiModeManager';
import Activity from 'android.app.Activity';
export class AppBaseInfoDeviceUtil{
public static getAppID(): string {
return Device.getAppId();
}
public static getAppName(context: Context): string {
let packageManager = context.getPackageManager();
return packageManager.getApplicationLabel(context.getApplicationInfo()).toString()
}
public static getPackageName(context: Context): string {
return context.getPackageName();
}
public static getAppVersionName(): string {
return Device.getAppVersion()["name"].toString();
}
public static getAppVersionCode(): string {
return Device.getAppVersion()["code"].toString();
}
public static getHostVersion(context: Context): string {
let packageManager = context.getPackageManager();
let applicationInfo = packageManager.getPackageInfo(context.getPackageName(), PackageManager.GET_ACTIVITIES);
return applicationInfo.versionName;
}
public static getHostCode(context: Context): string {
let packageManager = context.getPackageManager();
let applicationInfo = packageManager.getPackageInfo(context.getPackageName(), PackageManager.GET_ACTIVITIES);
return applicationInfo.versionCode+"";
}
public static isSystemNightMode(activity: Activity): boolean {
let uiModeManager = activity.getSystemService(Context.UI_MODE_SERVICE) as UiModeManager;
return uiModeManager.getNightMode() == UiModeManager.MODE_NIGHT_YES;
}
public static getOsLanguage(context: Context): string {
return Device.getLanguageInfo(context)["osLanguage"].toString();
}
public static getOsLanguageNormal(context: Context): string {
const LOCALE_ZH_HANS = 'zh-Hans'
const LOCALE_ZH_HANT = 'zh-Hant'
let locale = Device.getLanguageInfo(context)["appLanguage"].toString();
if (locale.indexOf('zh') === 0) {
if (locale.indexOf('-hans') > -1) {
return LOCALE_ZH_HANS;
}
if (locale.indexOf('-hant') > -1) {
return LOCALE_ZH_HANT;
}
if (locale.includes("-tw") || locale.includes("-hk") || locale.includes("-mo") || locale.includes("-cht")) {
return LOCALE_ZH_HANT;
}
return LOCALE_ZH_HANS;
} else {
return locale;
}
}
public static getAppInnerVersion(): string {
return Device.getInnerVersion();
}
}
\ No newline at end of file
import UTSAndroid from 'io.dcloud.uts.UTSAndroid';
import { AppBaseInfoDeviceUtil } from './device/AppBaseInfoDeviceUtil.uts';
import {
GetAppBaseInfoOptions,
GetAppBaseInfo,
GetAppBaseInfoResult
} from '../interface.uts'
export const getAppBaseInfo : GetAppBaseInfo = (config : GetAppBaseInfoOptions | null) : GetAppBaseInfoResult => {
let filter : Array<string> = [];
if (config != null && config.filter != null) {
filter = config.filter;
}
if (config == null || filter.length == 0) {
const defaultFilter = [
"appId",
"appName",
"appVersion",
"appVersionCode",
"appLanguage",
"language",
"version",
"appWgtVersion",
"hostLanguage",
"hostVersion",
"hostName",
"hostPackageName",
"hostSDKVersion",
"hostTheme",
"isUniAppX",
"uniCompileVersion",
"uniPlatform",
"uniRuntimeVersion",
"uniCompileVersionCode",
"uniRuntimeVersionCode"
];
filter = defaultFilter;
}
return getBaseInfo(filter);
}
function getBaseInfo(filterArray : Array<string>) : GetAppBaseInfoResult {
const activity = UTSAndroid.getUniActivity()!;
let result : GetAppBaseInfoResult = {};
if (filterArray.indexOf("appId") != -1) {
result.appId = AppBaseInfoDeviceUtil.getAppID();
}
if (filterArray.indexOf("appName") != -1) {
result.appName = UTSAndroid.getAppName();
}
if (UTSAndroid.isUniMp()) {
if (filterArray.indexOf("hostPackageName") != -1) {
result.hostPackageName = AppBaseInfoDeviceUtil.getPackageName(activity);
}
if (filterArray.indexOf("hostVersion") != -1) {
result.hostVersion = AppBaseInfoDeviceUtil.getHostVersion(activity);
}
if (filterArray.indexOf("hostName") != -1) {
result.hostName = AppBaseInfoDeviceUtil.getAppName(activity);
}
if (filterArray.indexOf("hostTheme") != -1) {
result.hostTheme = AppBaseInfoDeviceUtil.isSystemNightMode(activity) ? "dark" : "light";
}
if (filterArray.indexOf("hostLanguage") != -1) {
result.hostLanguage = AppBaseInfoDeviceUtil.getOsLanguage(activity);
}
if (filterArray.indexOf("appVersion") != -1) {
result.appVersion = AppBaseInfoDeviceUtil.getAppVersionName();
}
if (filterArray.indexOf("appVersionCode") != -1) {
result.appVersionCode = AppBaseInfoDeviceUtil.getAppVersionCode();
}
} else {
if (filterArray.indexOf("appVersion") != -1) {
result.appVersion = UTSAndroid.getAppVersion()["name"].toString();
}
if (filterArray.indexOf("appVersionCode") != -1) {
result.appVersionCode = UTSAndroid.getAppVersion()["code"].toString();
}
}
if (filterArray.indexOf("appLanguage") != -1) {
result.appLanguage = AppBaseInfoDeviceUtil.getOsLanguageNormal(activity);
}
if (filterArray.indexOf("language") != -1) {
result.language = AppBaseInfoDeviceUtil.getOsLanguage(activity);
}
if (filterArray.indexOf("version") != -1) {
result.version = AppBaseInfoDeviceUtil.getAppInnerVersion();
}
if (filterArray.indexOf("appWgtVersion") != -1) {
result.appWgtVersion = AppBaseInfoDeviceUtil.getAppVersionName();
}
if (filterArray.indexOf("isUniAppX") != -1) {
result.isUniAppX = UTSAndroid.isUniAppX();
}
if (filterArray.indexOf("uniCompileVersion") != -1) {
result.uniCompileVersion = UTSAndroid.getUniCompileVersion();
}
if (filterArray.indexOf("uniPlatform") != -1) {
result.uniPlatform = "app";
}
if (filterArray.indexOf("uniRuntimeVersion") != -1) {
result.uniRuntimeVersion = UTSAndroid.getUniRuntimeVersion();
}
if (filterArray.indexOf("uniCompileVersionCode") != -1) {
result.uniCompileVersionCode = convertVersionCode(UTSAndroid.getUniCompileVersion());
}
if (filterArray.indexOf("uniRuntimeVersionCode") != -1) {
result.uniRuntimeVersionCode = convertVersionCode(UTSAndroid.getUniRuntimeVersion());
}
return result;
}
const convertVersionCode = function(version: string): number {
let str = "";
let radixLength = 2;
let findDot = false;
const dotChar = ".".get(0);
for (let i = 0; i < version.length; i++) {
const char = version.get(i);
if(findDot){
if(char.isDigit()){
str += char;
}
radixLength --;
if(radixLength == 0){
break;
}
}else{
if(char.isDigit()){
str += char;
}else{
if(char == dotChar){
findDot = true;
str += char;
}
}
}
}
return parseFloat(str);
}
\ No newline at end of file
import { UTSiOS } from "DCloudUTSFoundation";
export class AppBaseInfoDeviceUtil {
public static getAppID() : string {
return UTSiOS.getAppId();
}
public static getAppName() : string {
return UTSiOS.getAppName();
}
public static getHostName() : string {
return UTSiOS.getHostName();
}
public static getHostTheme() : string {
return UTSiOS.getHostTheme();
}
public static getHostLanguage() : string {
return UTSiOS.getHostLanguage();
}
public static getHostVersion() : string {
return UTSiOS.getHostVersion();
}
public static getHostPackageName() : string {
return UTSiOS.getHostPackageName();
}
public static getAppVersion() : string {
return UTSiOS.getAppVersion();
}
public static getAppVersionCode() : string {
return UTSiOS.getAppVersionCode();
}
public static getAppWgtVersion() : string {
return UTSiOS.getAppWgtVersion();
}
public static getOsLanguage() : string {
return UTSiOS.getOsLanguage();
}
public static getOsLanguageNormal() : string {
const LOCALE_ZH_HANS = 'zh-Hans'
const LOCALE_ZH_HANT = 'zh-Hant'
let locale = UTSiOS.getOsLanguage();
if (locale.indexOf('zh') == 0) {
if (locale.indexOf('-hans') > -1) {
return LOCALE_ZH_HANS;
}
if (locale.indexOf('-hant') > -1) {
return LOCALE_ZH_HANT;
}
if (locale.includes("-tw") || locale.includes("-hk") || locale.includes("-mo") || locale.includes("-cht")) {
return LOCALE_ZH_HANT;
}
return LOCALE_ZH_HANS;
} else {
return locale;
}
}
public static getAppInnerVersion() : string {
return UTSiOS.getInnerVersion();
}
}
\ No newline at end of file
import { AppBaseInfoDeviceUtil } from './device/AppBaseInfoDeviceUtil.uts';
import { UTSiOS } from "DCloudUTSFoundation";
import {
GetAppBaseInfoOptions,
GetAppBaseInfo,
GetAppBaseInfoResult
} from '../interface.uts'
export const getAppBaseInfo : GetAppBaseInfo = (config : GetAppBaseInfoOptions | null) : GetAppBaseInfoResult => {
let filter : Array<string> = [];
if (config != null && config!.filter != null) {
filter = config!.filter;
}
if (config == null || filter.length == 0) {
const defaultFilter = [
"appId",
"appName",
"appVersion",
"appVersionCode",
"appLanguage",
"language",
"version",
"appWgtVersion",
"hostLanguage",
"hostVersion",
"hostName",
"hostPackageName",
"hostSDKVersion",
"hostTheme",
];
filter = defaultFilter;
}
return getBaseInfo(filter);
}
function getBaseInfo(filterArray : Array<string>) : GetAppBaseInfoResult {
let result : GetAppBaseInfoResult = {};
if (filterArray.indexOf("appId") != -1) {
result.appId = AppBaseInfoDeviceUtil.getAppID();
}
if (filterArray.indexOf("appName") != -1) {
result.appName = AppBaseInfoDeviceUtil.getAppName();
}
if (UTSiOS.isUniMp()) {
if (filterArray.indexOf("hostPackageName") != -1) {
result.hostPackageName = AppBaseInfoDeviceUtil.getHostPackageName();
}
if (filterArray.indexOf("hostVersion") != -1) {
result.hostVersion = AppBaseInfoDeviceUtil.getHostVersion();
}
if (filterArray.indexOf("hostName") != -1) {
result.hostName = AppBaseInfoDeviceUtil.getHostName();
}
if (filterArray.indexOf("hostTheme") != -1) {
result.hostTheme = AppBaseInfoDeviceUtil.getHostTheme();
}
if (filterArray.indexOf("hostLanguage") != -1) {
result.hostLanguage = AppBaseInfoDeviceUtil.getHostLanguage();
}
}
if (filterArray.indexOf("appVersion") != -1) {
result.appVersion = AppBaseInfoDeviceUtil.getAppVersion();
}
if (filterArray.indexOf("appVersionCode") != -1) {
result.appVersionCode = AppBaseInfoDeviceUtil.getAppVersionCode();
}
if (filterArray.indexOf("appLanguage") != -1) {
result.appLanguage = AppBaseInfoDeviceUtil.getOsLanguageNormal();
}
if (filterArray.indexOf("language") != -1) {
result.language = AppBaseInfoDeviceUtil.getOsLanguage();
}
if (filterArray.indexOf("version") != -1) {
result.version = AppBaseInfoDeviceUtil.getAppInnerVersion();
}
if (filterArray.indexOf("appWgtVersion") != -1) {
result.appWgtVersion = AppBaseInfoDeviceUtil.getAppWgtVersion();
}
return result;
}
\ No newline at end of file
export type GetAppBaseInfoOptions = {
/**
* @description 过滤字段的字符串数组,假如要获取指定字段,传入此数组。
*/
filter: Array<string>
};
export type GetAppBaseInfoResult = {
/**
* manifest.json 中应用appid,即DCloud appid。
*/
appId?: string,
/**
* `manifest.json` 中应用名称。
*/
appName?: string,
/**
* `manifest.json` 中应用版本名称。
*/
appVersion?: string,
/**
* `manifest.json` 中应用版本名号。
*/
appVersionCode?: string,
/**
* 应用设置的语言en、zh-Hans、zh-Hant、fr、es
*/
appLanguage?: string,
/**
* 应用设置的语言
*/
language?: string,
/**
* 引擎版本号。已废弃,仅为了向下兼容保留
* @deprecated 已废弃,仅为了向下兼容保留
*/
version?: string,
/**
* 应用资源(wgt)的版本名称。
*
* @uniPlatform {
* "app": {
* "android": {
* "osVer": "5.0",
* "uniVer": "√",
* "unixVer": "x"
* },
* "ios": {
* "osVer": "9.0",
* "uniVer": "√",
* "unixVer": "x"
* }
* }
* }
*/
appWgtVersion?: string,
/**
* 小程序宿主语言
*
* @uniPlatform {
* "app": {
* "android": {
* "osVer": "5.0",
* "uniVer": "√",
* "unixVer": "x"
* },
* "ios": {
* "osVer": "9.0",
* "uniVer": "√",
* "unixVer": "x"
* }
* }
* }
*/
hostLanguage?: string,
/**
* App、小程序宿主版本。
*
* @uniPlatform {
* "app": {
* "android": {
* "osVer": "5.0",
* "uniVer": "√",
* "unixVer": "x"
* },
* "ios": {
* "osVer": "9.0",
* "uniVer": "√",
* "unixVer": "x"
* }
* }
* }
*/
hostVersion?: string,
/**
* 小程序宿主名称
*
* @uniPlatform {
* "app": {
* "android": {
* "osVer": "5.0",
* "uniVer": "√",
* "unixVer": "x"
* },
* "ios": {
* "osVer": "9.0",
* "uniVer": "√",
* "unixVer": "x"
* }
* }
* }
*/
hostName?: string,
/**
* 小程序宿主包名
*
* @uniPlatform {
* "app": {
* "android": {
* "osVer": "5.0",
* "uniVer": "√",
* "unixVer": "x"
* },
* "ios": {
* "osVer": "9.0",
* "uniVer": "√",
* "unixVer": "x"
* }
* }
* }
*/
hostPackageName?: string,
/**
* uni小程序SDK版本、小程序客户端基础库版本
*
* @uniPlatform {
* "app": {
* "android": {
* "osVer": "5.0",
* "uniVer": "√",
* "unixVer": "x"
* },
* "ios": {
* "osVer": "9.0",
* "uniVer": "√",
* "unixVer": "x"
* }
* }
* }
*/
hostSDKVersion?: string,
/**
* 系统当前主题,取值为light或dark。微信小程序全局配置"darkmode":true时才能获取,否则为 undefined (不支持小游戏)
*
* @uniPlatform {
* "app": {
* "android": {
* "osVer": "5.0",
* "uniVer": "√",
* "unixVer": "x"
* },
* "ios": {
* "osVer": "9.0",
* "uniVer": "√",
* "unixVer": "x"
* }
* }
* }
*/
hostTheme?: string,
/**
* 是否uni-app x
*/
isUniAppX ?: boolean,
/**
* uni 编译器版本
*/
uniCompileVersion ?: string,
/**
* uni-app 运行平台。如:`app`、`mp-weixin`、`web`
*/
uniPlatform ?: string,
/**
* uni 运行时版本
*/
uniRuntimeVersion ?: string,
/**
* uni 编译器版本号
*/
uniCompileVersionCode?: number,
/**
* uni 运行时版本号
*/
uniRuntimeVersionCode?: number,
}
/**
* @param{GetAppBaseInfoOptions} [options=包含所有字段的过滤对象] 过滤的字段对象, 不传参数默认为获取全部字段。
*/
export type GetAppBaseInfo = (options?: GetAppBaseInfoOptions | null) => GetAppBaseInfoResult;
export interface Uni {
/**
* GetAppBaseInfo(Object object)
* @description
* 获取app基本信息
* @param {GetAppBaseInfoOptions} options [options=包含所有字段的过滤对象] 过滤的字段对象, 不传参数默认为获取全部字段。
* @return {object}
* @tutorial https://uniapp.dcloud.net.cn/api/system/getAppBaseInfo.html
* @uniPlatform {
* "app": {
* "android": {
* "osVer": "4.4",
* "uniVer": "√",
* "unixVer": "3.9+"
* },
* "ios": {
* "osVer": "9.0",
* "uniVer": "√",
* "unixVer": "x"
* }
* }
* }
* @example
```typescript
uni.getAppBaseInfo({
filter:[]
})
```
*/
getAppBaseInfo(options?: GetAppBaseInfoOptions | null): GetAppBaseInfoResult;
}
{
"id": "uni-getDeviceInfo",
"displayName": "uni-getDeviceInfo",
"version": "1.0.0",
"description": "uni-getDeviceInfo",
"keywords": [
"uni-getDeviceInfo"
],
"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": {
"getDeviceInfo": {
"name": "getDeviceInfo",
"app": {
"js": false,
"kotlin": true,
"swift": true
}
}
}
},
"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-getDeviceInfo
### 开发文档
[UTS 语法](https://uniapp.dcloud.net.cn/tutorial/syntax-uts.html)
[UTS 原生插件](https://uniapp.dcloud.net.cn/plugin/uts-plugin.html)
[Hello UTS](https://gitcode.net/dcloud/hello-uts/-/tree/dev)
\ No newline at end of file
import Activity from 'android.app.Activity';
import Configuration from 'android.content.res.Configuration';
import Context from 'android.content.Context';
import UiModeManager from 'android.app.UiModeManager';
import WindowManager from 'android.view.WindowManager';
import DisplayMetrics from 'android.util.DisplayMetrics';
import Build from 'android.os.Build';
import File from 'java.io.File';
import { EmulatorCheckUtil } from './EmulatorCheckUtil.uts'
import TextUtils from 'android.text.TextUtils';
import { UTSAndroid as Device } from "io.dcloud.uts";
import BufferedReader from 'java.io.BufferedReader';
import InputStreamReader from 'java.io.InputStreamReader';
import Exception from 'java.lang.Exception';
import KotlinArray from 'kotlin.Array'
export class DeviceUtil {
private static customOS: string | null = null
private static customOSVersion: string | null = null
private static readonly rootRelatedDirs = [
"/su", "/su/bin/su", "/sbin/su",
"/data/local/xbin/su", "/data/local/bin/su", "/data/local/su",
"/system/xbin/su",
"/system/bin/su", "/system/sd/xbin/su", "/system/bin/failsafe/su",
"/system/bin/cufsdosck", "/system/xbin/cufsdosck", "/system/bin/cufsmgr",
"/system/xbin/cufsmgr", "/system/bin/cufaevdd", "/system/xbin/cufaevdd",
"/system/bin/conbb", "/system/xbin/conbb"];
/**
* HarmonyOS 系统输出的
* 格式:2.0.0
*/
private static KEY_HARMONYOS_VERSION_NAME = "hw_sc.build.platform.version";
/**
* EMUI系统输出的
* 格式:EmotionUI_8.0.0
*/
private static KEY_EMUI_VERSION_NAME = "ro.build.version.emui";
/**
* MagicUI系统输出的
* 格式:3.1.0
*/
private static KEY_MAGICUI_VERSION = "ro.build.version.magic";
/**
* MIUI系统输出的
* 格式:V12
*/
private static KEY_MIUI_VERSION_NAME = "ro.miui.ui.version.name";
/**
* OPPO手机ColorOS系统输出的
* 格式:9
*/
private static KEY_COLOROS_VERSION_NAME = "ro.build.version.opporom";
/**
* VIVO手机系统输出的
* name格式:funtouch
* version格式: 9
*/
private static KEY_VIVO_VERSION_NAME = "ro.vivo.os.name";
private static KEY_VIVO_VERSION = "ro.vivo.os.version";
/**
* OonPlus手机系统输出的
* 格式:Hydrogen OS 11.0.7.10.KB05
*/
private static KEY_ONEPLUS_VERSION_NAME = "ro.rom.version";
/**
* 魅族手机系统输出的
*/
private static KEY_FLYME_VERSION_NAME = "ro.build.display.id";
/**
* nubia手机系统输出的
*/
private static KEY_NUBIA_VERSION_NAME = "ro.build.nubia.rom.name";
private static KEY_NUBIA_VERSION_CODE = "ro.build.nubia.rom.code";
public static getOrientation(activity: Activity): string {
const activityOrientation = activity.getResources().getConfiguration().orientation;
let outOrientation = "portrait";
if (activityOrientation == Configuration.ORIENTATION_LANDSCAPE) {
outOrientation = "landscape";
}
return outOrientation;
}
/**
* 获取屏幕像素比
*/
public static getScaledDensity(activity: Activity): number {
const windowManager = activity.getSystemService(Context.WINDOW_SERVICE) as WindowManager;
const displayMetrics = new DisplayMetrics();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
windowManager.getDefaultDisplay().getRealMetrics(displayMetrics);
} else {
windowManager.getDefaultDisplay().getMetrics(displayMetrics);
}
return displayMetrics.scaledDensity;
}
public static getSystemUIModeType(activity: Activity): string {
let uiModeManager = activity.getSystemService(Context.UI_MODE_SERVICE) as UiModeManager;
let modeType = "unknown";
switch (uiModeManager.getCurrentModeType()) {
case Configuration.UI_MODE_TYPE_TELEVISION:
modeType = "tv";
break;
case Configuration.UI_MODE_TYPE_WATCH:
modeType = "watch";
break;
case Configuration.UI_MODE_TYPE_NORMAL:
if (DeviceUtil.isTablet(activity)) {
modeType = "pad";
} else {
modeType = "phone";
}
break;
case Configuration.UI_MODE_TYPE_DESK:
modeType = "pc";
break;
case Configuration.UI_MODE_TYPE_UNDEFINED:
modeType = "undefined";
break;
case Configuration.UI_MODE_TYPE_CAR:
modeType = "car";
break;
case Configuration.UI_MODE_TYPE_VR_HEADSET:
modeType = "vr";
break;
case Configuration.UI_MODE_TYPE_APPLIANCE:
modeType = "appliance";
break;
}
return modeType;
}
/**
* 是否root
*/
public static hasRootPrivilege(): boolean {
let hasRootDir = false;
let rootDirs = DeviceUtil.rootRelatedDirs;
let dirCount = rootDirs.length;
let i = 0;
while (i < dirCount) {
let dir = rootDirs[i];
if ((new File(dir)).exists()) {
hasRootDir = true;
break;
}
i++;
}
return Build.TAGS != null && Build.TAGS.includes("test-keys") || hasRootDir;
}
public static isSimulator(context: Context): boolean {
return EmulatorCheckUtil.getSingleInstance().emulatorCheck(context);
}
public static getDeviceID(context: Context): string {
return Device.getDeviceID(context);
}
public static getOsLanguage(context: Context): string {
return Device.getLanguageInfo(context)["osLanguage"].toString();
}
public static getOsLanguageNormal(context: Context): string {
const LOCALE_ZH_HANS = 'zh-Hans'
const LOCALE_ZH_HANT = 'zh-Hant'
let locale = Device.getLanguageInfo(context)["appLanguage"].toString();
if (locale.indexOf('zh') === 0) {
if (locale.indexOf('-hans') > -1) {
return LOCALE_ZH_HANS;
}
if (locale.indexOf('-hant') > -1) {
return LOCALE_ZH_HANT;
}
if (locale.includes("-tw") || locale.includes("-hk") || locale.includes("-mo") || locale.includes("-cht")) {
return LOCALE_ZH_HANT;
}
return LOCALE_ZH_HANS;
} else {
return locale;
}
}
public static getAppInnerVersion(): string {
return Device.getInnerVersion();
}
public static getOaid(): string {
return Device.getOAID();
}
/**
* 是否为平板 不是太准确
*/
public static isTablet(activity: Activity): boolean {
return (activity.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_LARGE;
}
private static setCustomInfo(phoneBrand: string) {
try {
switch (DeviceUtil.deleteSpaceAndToUpperCase(phoneBrand)) {
case "HUAWEI":
if (DeviceUtil.isHarmonyOS()) {
DeviceUtil.customOSVersion = DeviceUtil.getSystemPropertyValue(DeviceUtil.KEY_HARMONYOS_VERSION_NAME);
DeviceUtil.customOS = "HarmonyOS";
} else {
DeviceUtil.customOS = "EMUI";
DeviceUtil.customOSVersion = DeviceUtil.getSystemPropertyValue(DeviceUtil.KEY_EMUI_VERSION_NAME);;
}
break;
case "HONOR":
if (DeviceUtil.isHarmonyOS()) {
DeviceUtil.customOS = "HarmonyOS";
if (!TextUtils.isEmpty(DeviceUtil.getSystemPropertyValue(DeviceUtil.KEY_HARMONYOS_VERSION_NAME))) {
DeviceUtil.customOSVersion = DeviceUtil.getSystemPropertyValue(DeviceUtil.KEY_HARMONYOS_VERSION_NAME);;
} else {
DeviceUtil.customOSVersion = "";
}
} else if (!TextUtils.isEmpty(DeviceUtil.getSystemPropertyValue(DeviceUtil.KEY_MAGICUI_VERSION))) {
DeviceUtil.customOS = "MagicUI";
DeviceUtil.customOSVersion = DeviceUtil.getSystemPropertyValue(DeviceUtil.KEY_MAGICUI_VERSION);
} else {
//格式:EmotionUI_8.0.0
DeviceUtil.customOS = "EMUI";
DeviceUtil.customOSVersion = DeviceUtil.getSystemPropertyValue(DeviceUtil.KEY_EMUI_VERSION_NAME);
}
break;
case "XIAOMI":
case "REDMI":
//格式:MIUIV12
DeviceUtil.customOS = "MIUI";
DeviceUtil.customOSVersion = DeviceUtil.getSystemPropertyValue(DeviceUtil.KEY_MIUI_VERSION_NAME);
break;
case "REALME":
case "OPPO":
//格式:ColorOSV2.1
DeviceUtil.customOS = "ColorOS";
DeviceUtil.customOSVersion = DeviceUtil.getSystemPropertyValue(DeviceUtil.KEY_COLOROS_VERSION_NAME);
break;
case "VIVO":
//格式:Funtouch9
DeviceUtil.customOS = "Funtouch";
DeviceUtil.customOSVersion = DeviceUtil.getSystemPropertyValue(DeviceUtil.KEY_VIVO_VERSION);
break;
case "ONEPLUS":
//格式:Hydrogen OS 11.0.7.10.KB05
DeviceUtil.customOS = "HydrogenOS";
DeviceUtil.customOSVersion = DeviceUtil.getSystemPropertyValue(DeviceUtil.KEY_ONEPLUS_VERSION_NAME);
break;
case "MEIZU":
//格式:Flyme 6.3.5.1G
DeviceUtil.customOS = "Flyme";
DeviceUtil.customOSVersion = DeviceUtil.getSystemPropertyValue(DeviceUtil.KEY_FLYME_VERSION_NAME);
break;
case "NUBIA":
//格式:nubiaUIV3.0
DeviceUtil.customOS = DeviceUtil.getSystemPropertyValue(DeviceUtil.KEY_NUBIA_VERSION_NAME);
DeviceUtil.customOSVersion = DeviceUtil.getSystemPropertyValue(DeviceUtil.KEY_NUBIA_VERSION_CODE);
break;
default:
DeviceUtil.customOS = "Android";
DeviceUtil.customOSVersion = Build.VERSION.RELEASE;
break;
}
} catch (e: Exception) {
}
}
/**
* 判断是否是华为鸿蒙系统,能否识别荣耀鸿蒙未知
*
* @return
*/
private static isHarmonyOS(): boolean {
try {
let classType = Class.forName("com.huawei.system.BuildEx");
let getMethod = classType.getMethod("getOsBrand");
let value = getMethod.invoke(classType) as string;
return !TextUtils.isEmpty(value);
} catch (e: Exception) {
return false;
}
}
/**
* 删除字符串中的空格并全部转成大写
* @param str
* @return
*/
public static deleteSpaceAndToUpperCase(str: string | null): string {
if (TextUtils.isEmpty(str)) {
return "";
}
return str!.replace(" ", "").toUpperCase();
}
private static getSystemPropertyValue(propName: string): string | null {
let value: string | null = null;
let roSecureObj: any | null;
try {
// Class.forName("java.lang.String")
const method = Class.forName("android.os.SystemProperties").getMethod("get", Class.forName("java.lang.String"));
roSecureObj = method.invoke(null, propName);
if (roSecureObj != null) {
value = roSecureObj as string;
}
} catch (e: Exception) {
}
return value;
}
public static listeningForADB(): boolean {
let cmd : KotlinArray<string> = arrayOf<string>("/bin/sh", "-c", "getprop | grep init.svc.adbd");
try{
Runtime.getRuntime().exec(cmd);
}catch(e:Exception){
cmd = arrayOf<string>("/system/bin/sh", "-c", "getprop | grep init.svc.adbd");
try{
Runtime.getRuntime().exec(cmd);
}catch(e:Exception){
return false
}
}
let exec = Runtime.getRuntime().exec(cmd);
let bufferedReader = new BufferedReader(new InputStreamReader(exec.getInputStream(), "utf-8"));
let tmp = new CharArray(1024);
let result = false;
do {
let len = bufferedReader.read(tmp);
if (len == -1) {
break;
}
let res = new String(tmp, 0, len);
result = res.includes("running");
} while (true)
exec.getInputStream().close();
bufferedReader.close();
return result;
}
}
import Context from "android.content.Context";
import Locale from "java.util.Locale";
import File from "java.io.File";
import SensorManager from "android.hardware.SensorManager";
import Sensor from "android.hardware.Sensor";
import PackageManager from 'android.content.pm.PackageManager';
class CheckResult {
public result: Int;
public value: string | null;
constructor(result: Int, value: string | null) {
this.result = result;
this.value = value;
}
}
export class EmulatorCheckUtil {
private static INSTANCE: EmulatorCheckUtil | null = null;
public static readonly RESULT_MAYBE_EMULATOR:Int = 0; //可能是模拟器
public static readonly RESULT_EMULATOR:Int = 1; //模拟器
public static readonly RESULT_UNKNOWN:Int = 2; //可能是真机
private static known_pkgNames =[
"sdcard/Android/data/com.bluestacks.home", //蓝叠
"sdcard/Android/data/com.bluestacks.settings", //蓝叠
"sdcard/Android/data/com.microvirt.guide", //逍遥
"sdcard/Android/data/com.microvirt.launcher2" //逍遥
];
public static getSingleInstance(): EmulatorCheckUtil {
if (EmulatorCheckUtil.INSTANCE == null) {
EmulatorCheckUtil.INSTANCE = new EmulatorCheckUtil();
}
return EmulatorCheckUtil.INSTANCE!;
}
public emulatorCheck(context: Context): boolean {
if (context == null) {
throw new IllegalArgumentException("context must not be null");
}
let suspectCount = 0;
//检测硬件名称
let hardwareResult = this.checkFeaturesByHardware();
switch (hardwareResult.result) {
case EmulatorCheckUtil.RESULT_MAYBE_EMULATOR:
++suspectCount;
break;
case EmulatorCheckUtil.RESULT_EMULATOR:
return true;
}
//通过pkgName检测
let blueStacksResult = this.checkPkgNameForEmulator();
switch (blueStacksResult.result) {
case EmulatorCheckUtil.RESULT_MAYBE_EMULATOR:
++suspectCount;
break;
case EmulatorCheckUtil.RESULT_EMULATOR:
return true;
}
//检测渠道
let flavorResult = this.checkFeaturesByFlavor();
switch (flavorResult.result) {
case EmulatorCheckUtil.RESULT_MAYBE_EMULATOR:
++suspectCount;
break;
case EmulatorCheckUtil.RESULT_EMULATOR:
return true;
}
//检测设备型号
let modelResult = this.checkFeaturesByModel();
switch (modelResult.result) {
case EmulatorCheckUtil.RESULT_MAYBE_EMULATOR:
++suspectCount;
break;
case EmulatorCheckUtil.RESULT_EMULATOR:
return true;
}
//检测硬件制造商
let manufacturerResult = this.checkFeaturesByManufacturer();
switch (manufacturerResult.result) {
case EmulatorCheckUtil.RESULT_MAYBE_EMULATOR:
++suspectCount;
break;
case EmulatorCheckUtil.RESULT_EMULATOR:
return true;
}
//检测主板名称
let boardResult = this.checkFeaturesByBoard();
switch (boardResult.result) {
case EmulatorCheckUtil.RESULT_MAYBE_EMULATOR:
++suspectCount;
break;
case EmulatorCheckUtil.RESULT_EMULATOR:
return true;
}
//检测主板平台
let platformResult = this.checkFeaturesByPlatform();
switch (platformResult.result) {
case EmulatorCheckUtil.RESULT_MAYBE_EMULATOR:
++suspectCount;
break;
case EmulatorCheckUtil.RESULT_EMULATOR:
return true;
}
//检测基带信息
let baseBandResult = this.checkFeaturesByBaseBand();
switch (baseBandResult.result) {
case EmulatorCheckUtil.RESULT_MAYBE_EMULATOR:
suspectCount += 2; //模拟器基带信息为null的情况概率相当大
break;
case EmulatorCheckUtil.RESULT_EMULATOR:
return true;
}
//检测传感器数量
let sensorNumber = this.getSensorNumber(context);
if (sensorNumber <= 7) ++suspectCount;
//检测已安装第三方应用数量
/*int userAppNumber = getUserAppNumber();
if (userAppNumber <= 5) ++suspectCount;*/
//检测是否支持闪光灯
let supportCameraFlash = this.supportCameraFlash(context);
if (!supportCameraFlash) ++suspectCount;
//检测是否支持蓝牙
let supportBluetooth = this.supportBluetooth(context);
if (!supportBluetooth) ++suspectCount;
//检测光线传感器
let hasLightSensor = this.hasLightSensor(context);
if (!hasLightSensor) ++suspectCount;
//检测进程组信息
/*CheckResult cgroupResult = checkFeaturesByCgroup();
if (cgroupResult.result == RESULT_MAYBE_EMULATOR) ++suspectCount;*/
//嫌疑值大于3,认为是模拟器
return suspectCount > 3;
}
private getProperty(propName: string): string | null {
let value: string | null = null;
let roSecureObj: any | null = null;
try {
const method = Class.forName("android.os.SystemProperties").getMethod(
"get",
Class.forName("java.lang.String")
);
roSecureObj = method.invoke(null, propName);
if (roSecureObj != null) {
value = roSecureObj as string;
}
} catch (e: Exception) {
}
return value;
}
/**
* 特征参数-硬件名称
*
* @return 0表示可能是模拟器,1表示模拟器,2表示可能是真机
*/
private checkFeaturesByHardware(): CheckResult {
let hardware = this.getProperty("ro.hardware");
if (null == hardware) {
return new CheckResult(EmulatorCheckUtil.RESULT_MAYBE_EMULATOR, null);
}
let result: Int | null;
let tempValue = hardware.toLowerCase(Locale.ENGLISH);
switch (tempValue) {
case "ttvm": //天天模拟器
case "nox": //夜神模拟器
case "cancro": //网易MUMU模拟器
case "intel": //逍遥模拟器
case "vbox":
case "vbox86": //腾讯手游助手
case "android_x86": //雷电模拟器
result = EmulatorCheckUtil.RESULT_EMULATOR;
break;
default:
result = EmulatorCheckUtil.RESULT_UNKNOWN;
break;
}
return new CheckResult(result, hardware);
}
/**
* 特征参数-渠道
*
* @return 0表示可能是模拟器,1表示模拟器,2表示可能是真机
*/
private checkFeaturesByFlavor(): CheckResult {
let flavor = this.getProperty("ro.build.flavor");
if (null == flavor) {
return new CheckResult(EmulatorCheckUtil.RESULT_MAYBE_EMULATOR, null);
}
let result: Int | null;
let tempValue = flavor.toLowerCase(Locale.ENGLISH);
if (tempValue.includes("vbox")) {
result = EmulatorCheckUtil.RESULT_EMULATOR;
} else if (tempValue.includes("sdk_gphone")) {
result = EmulatorCheckUtil.RESULT_EMULATOR;
} else {
result = EmulatorCheckUtil.RESULT_UNKNOWN;
}
return new CheckResult(result, flavor);
}
private checkPkgNameForEmulator(): CheckResult {
let result = EmulatorCheckUtil.RESULT_UNKNOWN;
let accordSize = 0;
for (let i = 0; i < EmulatorCheckUtil.known_pkgNames.length; i++) {
let file_name = EmulatorCheckUtil.known_pkgNames[i];
let qemu_file = new File(file_name);
if (qemu_file.exists()) {
accordSize++;
} else {
result = EmulatorCheckUtil.RESULT_MAYBE_EMULATOR;
}
if (accordSize > 2) {
break;
}
}
switch (accordSize) {
case 1: {
result = EmulatorCheckUtil.RESULT_MAYBE_EMULATOR;
break;
}
case 2: {
result = EmulatorCheckUtil.RESULT_EMULATOR;
break;
}
}
return new CheckResult(result, "PkgName");
}
/**
* 特征参数-设备型号
*
* @return 0表示可能是模拟器,1表示模拟器,2表示可能是真机
*/
private checkFeaturesByModel(): CheckResult {
let model = this.getProperty("ro.product.model");
if (null == model) {
return new CheckResult(EmulatorCheckUtil.RESULT_MAYBE_EMULATOR, null);
}
let result: Int | null;
let tempValue = model.toLowerCase(Locale.ENGLISH);
if (tempValue.includes("google_sdk")) {
result = EmulatorCheckUtil.RESULT_EMULATOR;
} else if (tempValue.includes("emulator")) {
result = EmulatorCheckUtil.RESULT_EMULATOR;
} else if (tempValue.includes("android sdk built for x86")) {
result = EmulatorCheckUtil.RESULT_EMULATOR;
} else {
result = EmulatorCheckUtil.RESULT_UNKNOWN;
}
return new CheckResult(result, model);
}
/**
* 特征参数-硬件制造商
*
* @return 0表示可能是模拟器,1表示模拟器,2表示可能是真机
*/
private checkFeaturesByManufacturer(): CheckResult {
let manufacturer = this.getProperty("ro.product.manufacturer");
if (null == manufacturer)
return new CheckResult(EmulatorCheckUtil.RESULT_MAYBE_EMULATOR, null);
let result: Int | null;
let tempValue = manufacturer.toLowerCase(Locale.ENGLISH);
if (tempValue.includes("genymotion")) {
result = EmulatorCheckUtil.RESULT_EMULATOR;
} else if (tempValue.includes("netease")) {
result = EmulatorCheckUtil.RESULT_EMULATOR; //网易MUMU模拟器
} else {
result = EmulatorCheckUtil.RESULT_UNKNOWN;
}
return new CheckResult(result, manufacturer);
}
/**
* 特征参数-主板名称
*
* @return 0表示可能是模拟器,1表示模拟器,2表示可能是真机
*/
private checkFeaturesByBoard(): CheckResult {
let board = this.getProperty("ro.product.board");
if (null == board) {
return new CheckResult(EmulatorCheckUtil.RESULT_MAYBE_EMULATOR, null);
}
let result: Int | null;
let tempValue = board.toLowerCase(Locale.ENGLISH);
if (tempValue.includes("android")) {
result = EmulatorCheckUtil.RESULT_EMULATOR;
} else if (tempValue.includes("goldfish")) {
result = EmulatorCheckUtil.RESULT_EMULATOR;
} else {
result = EmulatorCheckUtil.RESULT_UNKNOWN;
}
return new CheckResult(result, board);
}
/**
* 特征参数-主板平台
*
* @return 0表示可能是模拟器,1表示模拟器,2表示可能是真机
*/
private checkFeaturesByPlatform(): CheckResult {
let platform = this.getProperty("ro.board.platform");
if (null == platform)
return new CheckResult(EmulatorCheckUtil.RESULT_MAYBE_EMULATOR, null);
let result: Int | null;
let tempValue = platform.toLowerCase(Locale.ENGLISH);
if (tempValue.includes("android")) {
result = EmulatorCheckUtil.RESULT_EMULATOR;
} else {
result = EmulatorCheckUtil.RESULT_UNKNOWN;
}
return new CheckResult(result, platform);
}
/**
* 特征参数-基带信息
*
* @return 0表示可能是模拟器,1表示模拟器,2表示可能是真机
*/
private checkFeaturesByBaseBand(): CheckResult {
let baseBandVersion = this.getProperty("gsm.version.baseband");
if (null == baseBandVersion) {
return new CheckResult(EmulatorCheckUtil.RESULT_MAYBE_EMULATOR, null);
}
let result: Int | null;
if (baseBandVersion.includes("1.0.0.0")) {
result = EmulatorCheckUtil.RESULT_EMULATOR;
} else {
result = EmulatorCheckUtil.RESULT_UNKNOWN;
}
return new CheckResult(result, baseBandVersion);
}
/**
* 获取传感器数量
*/
private getSensorNumber(context: Context): Int {
let sm = context.getSystemService(Context.SENSOR_SERVICE) as SensorManager;
return sm.getSensorList(Sensor.TYPE_ALL).size;
}
/**
* 是否支持闪光灯
*/
private supportCameraFlash(context: Context): boolean {
return context
.getPackageManager()
.hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH);
}
/**
* 是否支持蓝牙
*/
private supportBluetooth(context: Context): boolean {
return context
.getPackageManager()
.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);
}
/**
* 判断是否存在光传感器来判断是否为模拟器
* 部分真机也不存在温度和压力传感器。其余传感器模拟器也存在。
*
* @return false为模拟器
*/
private hasLightSensor(context: Context): boolean {
let sensorManager = context.getSystemService(
Context.SENSOR_SERVICE
) as SensorManager;
let sensor = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT); //光线传感器
return null != sensor;
}
}
import Build from 'android.os.Build';
import { UTSAndroid } from "io.dcloud.uts";
import { DeviceUtil } from './device/DeviceUtil.uts';
import { GetDeviceInfo, GetDeviceInfoOptions, GetDeviceInfoResult } from '../interface.uts'
export const getDeviceInfo : GetDeviceInfo = (config : GetDeviceInfoOptions | null) : GetDeviceInfoResult => {
let filter : Array<string> = [];
if (config != null && config.filter != null) {
filter = config.filter;
}
if (config == null || filter.length == 0) {
const defaultFilter = [
"brand",
"deviceBrand",
"deviceId",
"model",
"deviceModel",
"deviceType",
"deviceOrientation",
"devicePixelRatio",
"system",
"platform",
"oaid",
"isRoot",
"isSimulator",
"isUSBDebugging"
];
filter = defaultFilter;
}
return getBaseInfo(filter);
}
function getBaseInfo(filterArray : Array<string>) : GetDeviceInfoResult {
const activity = UTSAndroid.getUniActivity()!;
let result : GetDeviceInfoResult = {};
if (filterArray.indexOf("brand") != -1) {
result.brand = Build.MANUFACTURER;
}
if (filterArray.indexOf("deviceBrand") != -1) {
result.deviceBrand = Build.MANUFACTURER;
}
if (filterArray.indexOf("model") != -1) {
result.model = Build.MODEL;
}
if (filterArray.indexOf("deviceModel") != -1) {
result.deviceModel = Build.MODEL;
}
if (filterArray.indexOf("deviceType") != -1) {
result.deviceType = DeviceUtil.getSystemUIModeType(activity);
}
if (filterArray.indexOf("deviceOrientation") != -1) {
result.deviceOrientation = DeviceUtil.getOrientation(activity);
}
if (filterArray.indexOf("deviceId") != -1) {
result.deviceId = DeviceUtil.getDeviceID(activity);
}
if (filterArray.indexOf("devicePixelRatio") != -1) {
result.devicePixelRatio = DeviceUtil.getScaledDensity(activity) + "";
}
if (filterArray.indexOf("system") != -1) {
result.system = "Android " + Build.VERSION.RELEASE;
}
if (filterArray.indexOf("platform") != -1) {
result.platform = "android";
}
if (filterArray.indexOf("oaid") != -1) {
result.oaid = DeviceUtil.getOaid();
}
if (filterArray.indexOf("isRoot") != -1) {
result.isRoot = DeviceUtil.hasRootPrivilege();
}
if (filterArray.indexOf("isSimulator") != -1) {
result.isSimulator = DeviceUtil.isSimulator(activity);
}
if (filterArray.indexOf("isUSBDebugging") != -1) {
result.isUSBDebugging = DeviceUtil.listeningForADB();
}
return result;
}
\ No newline at end of file
import { UIDevice, UIApplication, UIInterfaceOrientation, UIScreen } from 'UIKit';
import { NSLocale, URL, FileManager } from 'Foundation';
import { ATTrackingManager } from 'AppTrackingTransparency';
import { ASIdentifierManager } from 'AdSupport';
import { DispatchSemaphore, DispatchQueue } from 'Dispatch';
export class DeviceUtil {
public static isPad(): boolean {
return UIDevice.current.userInterfaceIdiom == UIUserInterfaceIdiom.pad
}
public static getOSVersion(): string {
return UIDevice.current.systemVersion;
}
public static getLan(): string {
let currentLanguage = NSLocale.preferredLanguages[0];
return currentLanguage == null ? "" : currentLanguage
}
public static getOrientation(): string {
let orientation = "portrait";
DispatchQueue.main.sync(execute = () => {
const orient = UIApplication.shared.statusBarOrientation;
if (orient == UIInterfaceOrientation.landscapeLeft || orient == UIInterfaceOrientation.landscapeRight) {
orientation = "landscape";
}
})
return orientation;
}
public static getScreenScale(): string {
return UIScreen.main.scale.description;
}
public static getIdfa(): string {
if (UTSiOS.available("iOS 14, *")) {
if (ATTrackingManager.trackingAuthorizationStatus == ATTrackingManager.AuthorizationStatus.notDetermined) {
ATTrackingManager.requestTrackingAuthorization(completionHandler = (status) => { });
} else if (ATTrackingManager.trackingAuthorizationStatus == ATTrackingManager.AuthorizationStatus.authorized) {
return ASIdentifierManager.shared().advertisingIdentifier.uuidString;
}
return "";
}
return ASIdentifierManager.shared().advertisingIdentifier.uuidString;
}
public static hasRootPrivilege(): boolean {
let url = new URL(string = "cydia://");
let canOpenUrl = false;
DispatchQueue.main.sync(execute = () => {
canOpenUrl = UIApplication.shared.canOpenURL(url!)
})
if (canOpenUrl) {
return true;
}
let jailbreakToolPaths = [
"/Applications/Cydia.app",
"/Library/MobileSubstrate/MobileSubstrate.dylib",
"/bin/bash",
"/usr/sbin/sshd",
"/etc/apt"
];
let i = 0;
while (i < jailbreakToolPaths.length) {
if (FileManager.default.fileExists(atPath = jailbreakToolPaths[i])) {
return true;
}
i++;
}
return false;
}
}
\ No newline at end of file
import { UTSiOS } from "DCloudUTSFoundation";
import { DeviceUtil } from './device/DeviceUtil.uts';
import { GetDeviceInfo, GetDeviceInfoOptions, GetDeviceInfoResult } from '../interface.uts'
export const getDeviceInfo : GetDeviceInfo = (config : GetDeviceInfoOptions | null) : GetDeviceInfoResult => {
let filter : Array<string> = [];
if (config != null && config?.filter != null) {
let temp = config?.filter;
filter = temp!;
}
if (config == null || filter.length == 0) {
const defaultFilter = [
"brand",
"deviceBrand",
"deviceId",
"model",
"deviceModel",
"deviceType",
"deviceOrientation",
"devicePixelRatio",
"system",
"platform",
"idfa",
"isRoot",
"isSimulator"
];
filter = defaultFilter;
}
return getBaseInfo(filter);
}
function getBaseInfo(filterArray : Array<string>) : GetDeviceInfoResult {
const osVersion = DeviceUtil.getOSVersion();
let result : GetDeviceInfoResult = {};
if (filterArray.indexOf("brand") != -1) {
result.brand = "apple";
}
if (filterArray.indexOf("deviceBrand") != -1) {
result.deviceBrand = "apple";
}
if (filterArray.indexOf("deviceId") != -1) {
result.deviceId = UTSiOS.getDeviceId();
}
if (filterArray.indexOf("model") != -1) {
result.model = UTSiOS.getModel();
}
if (filterArray.indexOf("deviceModel") != -1) {
result.deviceModel = UTSiOS.getModel();
}
if (filterArray.indexOf("deviceType") != -1) {
result.deviceType = DeviceUtil.isPad() ? "pad" : "phone";
}
if (filterArray.indexOf("deviceOrientation") != -1) {
result.deviceOrientation = DeviceUtil.getOrientation();
}
if (filterArray.indexOf("devicePixelRatio") != -1) {
result.devicePixelRatio = DeviceUtil.getScreenScale();
}
if (filterArray.indexOf("system") != -1) {
result.system = String(format = "iOS %@", osVersion);
}
if (filterArray.indexOf("platform") != -1) {
result.platform = "ios";
}
if (filterArray.indexOf("idfa") != -1) {
result.idfa = DeviceUtil.getIdfa();
}
if (filterArray.indexOf("isRoot") != -1) {
result.isRoot = DeviceUtil.hasRootPrivilege();
}
if (filterArray.indexOf("isSimulator") != -1) {
result.isSimulator = UTSiOS.isSimulator();
}
return result;
}
\ No newline at end of file
export type GetDeviceInfoOptions = {
/**
* @description 过滤字段的字符串数组,假如要获取指定字段,传入此数组。
*/
filter: Array<string>
}
export type GetDeviceInfoResult = {
/**
* 设备品牌
*/
brand?: string
/**
* 设备品牌
*/
deviceBrand?: string,
/**
* 设备 id 。由 uni-app 框架生成并存储,清空 Storage 会导致改变
*/
deviceId?: string,
/**
* 设备型号
*/
model?: string,
/**
* 设备型号
*/
deviceModel?: string,
/**
* 设备类型phone、pad、pc
*/
deviceType?: string,
/**
* 设备方向 竖屏 portrait、横屏 landscape
*/
deviceOrientation?: string,
/**
* 设备像素比
*/
devicePixelRatio?: string,
/**
* 操作系统及版本
*/
system?: string,
/**
* 客户端平台
*/
platform?: string,
/**
* oaid标识 Android专有
*
* @uniPlatform {
* "app": {
* "android": {
* "osVer": "5.0",
* "uniVer": "√",
* "unixVer": "√"
* },
* "ios": {
* "osVer": "9.0",
* "uniVer": "x",
* "unixVer": "x"
* }
* }
* }
*/
oaid?: string,
/**
* 是否root
*/
isRoot?: boolean,
/**
* 是否是模拟器
*/
isSimulator?: boolean,
/**
* adb是否开启
*
* @uniPlatform {
* "app": {
* "android": {
* "osVer": "5.0",
* "uniVer": "√",
* "unixVer": "√"
* },
* "ios": {
* "osVer": "9.0",
* "uniVer": "x",
* "unixVer": "x"
* }
* }
* }
*/
isUSBDebugging?: boolean,
/**
* idfa标识 iOS专有
*
* @uniPlatform {
* "app": {
* "android": {
* "osVer": "5.0",
* "uniVer": "x",
* "unixVer": "x"
* },
* "ios": {
* "osVer": "9.0",
* "uniVer": "√",
* "unixVer": "x"
* }
* }
* }
*/
idfa?: string,
/**
* 应用平台
*/
}
/**
* @param [options=包含所有字段的过滤对象] 过滤的字段对象, 不传参数默认为获取全部字段。
*/
export type GetDeviceInfo = (options?: GetDeviceInfoOptions | null) => GetDeviceInfoResult;
export interface Uni {
/**
* GetDeviceInfo(Object object)
* @description
* 获取设备信息
* @param {GetDeviceInfoOptions} options [options=包含所有字段的过滤对象] 过滤的字段对象, 不传参数默认为获取全部字段。
* @return {object}
* @tutorial https://uniapp.dcloud.net.cn/api/system/getDeviceInfo.html
* @uniPlatform {
* "app": {
* "android": {
* "osVer": "4.4",
* "uniVer": "√",
* "unixVer": "3.9+"
* },
* "ios": {
* "osVer": "9.0",
* "uniVer": "√",
* "unixVer": "x"
* }
* }
* }
* @example
```typescript
uni.getDeviceInfo({
filter:[]
})
```
*/
getDeviceInfo(options?: GetDeviceInfoOptions | null): GetDeviceInfoResult;
}
{
"id": "uni-getLocation-system",
"displayName": "uni-getLocation-system",
"version": "1.0.0",
"description": "uni-getLocation-system",
"keywords": [
"uni-getLocation-system"
],
"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": {
"uni-ext-api": {
"uni": {
"getLocation": {
"name": "getLocation",
"app": {
"js": false,
"kotlin": true,
"swift": false
}
}
}
},
"dependencies": [],
"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
# uts-location
### 开发文档
[UTS 语法](https://uniapp.dcloud.net.cn/tutorial/syntax-uts.html)
[UTS API插件](https://uniapp.dcloud.net.cn/plugin/uts-plugin.html)
[UTS 组件插件](https://uniapp.dcloud.net.cn/plugin/uts-component.html)
[Hello UTS](https://gitcode.net/dcloud/hello-uts)
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"
package="io.dcloud.uni.getlocation.system">
<!--permissions-->
<!-- 通过GPS得到精确位置 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<!-- 通过网络得到粗略位置 -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<!-- 访问网络,某些位置信息需要从网络服务器获取 -->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>
import { GetLocation, GetLocationOptions, GetLocationSuccess,GetLocationFail } from "../interface.uts"
import UTSAndroid from 'io.dcloud.uts.UTSAndroid';
import Context from 'android.content.Context';
import LocationManager from 'android.location.LocationManager';
import Criteria from 'android.location.Criteria';
import Location from 'android.location.Location';
import LocationListener from 'android.location.LocationListener';
/**
* 对外的函数接口
*/
export const getLocation : GetLocation = function (options : GetLocationOptions) {
/**
* 准备权限
*/
let permissionNeed : string[] = utsArrayOf("android.permission.ACCESS_FINE_LOCATION");
UTSAndroid.requestSystemPermission(UTSAndroid.getUniActivity()!, permissionNeed, function (allRight:boolean,_grantedList:string[]) {
if (allRight) {
// 交给目前的location 引擎,真实执行
getLocationImpl(options)
}
}, function (_doNotAskAgain:boolean,_grantedList:string[]) {
console.log("用户拒绝了部分权限:")
let err = new UniError("uni-getLocation-system",-10,"permission missed.");
options.fail?.(err)
options.complete?.(err)
})
}
/****************************************内部功能实现****************************************************/
/**
* 全局信息处理
*/
class Global {
/**
* 默认实现
*/
static lastLocation : Location | null = null;
}
/**
* 封装系统监听回调
*/
class CustomSystemLocationListener extends LocationListener {
override onLocationChanged(location : Location) : void {
Global.lastLocation = location
}
}
/**
* 真实的执行位置定位
*/
function getLocationImpl(options : GetLocationOptions) {
/**
* add since 2023-09-14 增加默认值兼容逻辑
*/
if(options.type == null){
options.type = 'wgs84'
}
if(options.highAccuracyExpireTime == null){
options.highAccuracyExpireTime = 3000
}
if(options.type != 'wgs84'){
// 系统定位只支持wgs84,如果不是则报错
let err = new UniError("uni-getLocation-system",-1,"system location support wgs84 only.");
options.fail?.(err)
options.complete?.(err)
return
}
if(options.geocode != null && options.geocode == true){
// 系统定位不支持逆地理编码
let err = new UniError("uni-getLocation-system",-2,"system location not support geocode.");
options.fail?.(err)
options.complete?.(err)
return
}
let locationManager = UTSAndroid.getAppContext()!.getSystemService(Context.LOCATION_SERVICE) as LocationManager;
let criteria = new Criteria()
// 用户明确开启了高度
if (options.altitude != null && options.altitude == true) {
criteria.setAltitudeRequired(true)
}
// 设置精度
if (options.isHighAccuracy != null && options.isHighAccuracy == true) {
criteria.setAccuracy(Criteria.ACCURACY_FINE)
} else{
criteria.setAccuracy(Criteria.ACCURACY_COARSE)
}
criteria.setPowerRequirement(Criteria.POWER_LOW)
criteria.setSpeedRequired(true)
/**
* 如果存在gps,那么优先gps,这样才有高度信息
*/
let providerName:string|null = "gps"
if(!locationManager.getProviders(criteria, true).contains("gps")){
providerName = locationManager.getBestProvider(criteria, true)
}
if (providerName == null) {
// 没有找到合法的系统定位能力提供者,错误的逻辑 todo
let err = new UniError("uni-getLocation-system",-3,"Provider is not find,Please ensure that the device location function is turned on");
options.fail?.(err)
options.complete?.(err)
return;
}
// 兜底的逻辑是上次定位的信息
Global.lastLocation = locationManager.getLastKnownLocation(providerName)
let systemListener = new CustomSystemLocationListener()
locationManager.requestLocationUpdates(providerName, 2000, 0.0.toFloat(), systemListener)
// 默认超时6000ms
let timeoutMill:number = 6000;
/**
* 只有设置超出3000ms 才会认为有效
* https://uniapp.dcloud.net.cn/api/location/location.html#getlocation
*/
if(options.highAccuracyExpireTime != null && options.highAccuracyExpireTime! >= 3000){
timeoutMill = options.highAccuracyExpireTime!
}
let taskId = 0
let startTimeMill = (new Date()).getTime()
// 不管返回结果如何,延迟2s 返回数据
taskId = setInterval(function () {
if (Global.lastLocation == null) {
// 没有得到想要的位置,统计错误计数+1
let currentTimeMill = (new Date()).getTime()
let diffTimeNum = currentTimeMill - startTimeMill
if (diffTimeNum > timeoutMill) {
locationManager.removeUpdates(systemListener)
// 超过6s了,返回错误
clearInterval(taskId)
let err = new UniError("uni-getLocation-system",-4,"location fail: timeout");
options.fail?.(err)
options.complete?.(err)
}
} else {
locationManager.removeUpdates(systemListener)
clearInterval(taskId)
let ret : GetLocationSuccess = {
latitude: Global.lastLocation!.getLatitude(),
longitude: Global.lastLocation!.getLongitude(),
speed: Global.lastLocation!.getSpeed(),
accuracy: Global.lastLocation!.getAccuracy(),
altitude: Global.lastLocation!.getAltitude(),
verticalAccuracy: 0,
horizontalAccuracy: Global.lastLocation!.getAccuracy(),
address: null
}
options.success?.(ret)
Global.lastLocation = null
}
}, 2000);
}
export interface Uni {
/**
* @description 获取当前的地理位置、速度
* @param {GetLocation} option
* @example
* ```typescript
* uni.getLocation({
* type: 'wgs84',
* success: function (res) {
* console.log('当前位置的经度:' + res.longitude);
* console.log('当前位置的纬度:' + res.latitude);
* }
* });
* ```
* @tutorial [](http://uniapp.dcloud.io/api/location/location?id=getlocation)
* @uniPlatform {
* "app": {
* "android": {
* "osVer": "4.4.4",
* "uniVer": "√",
* "unixVer": "3.9.0"
* },
* "ios": {
* "osVer": "x",
* "uniVer": "x",
* "unixVer": "x"
* }
* }
* }
*/
getLocation(options: GetLocationOptions):void;
}
export type GetLocation = (options: GetLocationOptions) => void;
export type GetLocationSuccess = {
/**
* 纬度,浮点数,范围为-90~90,负数表示南纬
* @defaultValue 0
*/
latitude: number,
/**
* 经度,范围为-180~180,负数表示西经
* @defaultValue 0
*/
longitude: number,
/**
* 速度,浮点数,单位m/s
* @defaultValue 0
*/
speed: number,
/**
* 位置的精确度
*/
accuracy: number,
/**
* 高度,单位 m
* @defaultValue 0
*/
altitude: number,
/**
* 垂直精度,单位 m(Android 无法获取,返回 0)
* @defaultValue 0
*/
verticalAccuracy: number,
/**
* 水平精度,单位 m
* @defaultValue 0
*/
horizontalAccuracy: number,
/**
* 地址信息
* @defaultValue null
*/
address: any | null
};
type GetLocationSuccessCallback = (result: GetLocationSuccess) => void;
type GetLocationFailCallback = (result: UniError) => void;
type GetLocationComplete = any;
type GetLocationCompleteCallback = (result: GetLocationComplete) => void;
export type GetLocationOptions = {
/**
* 默认为 wgs84 返回 gps 坐标,gcj02 返回可用于uni.openLocation的坐标
* @defaultValue wgs84
*/
type?: string | null,
/**
* 传入 true 会返回高度信息,由于获取高度需要较高精确度,会减慢接口返回速度
* @type boolean
* @defaultValue false
*/
altitude?: boolean | null,
/**
* 传入 true 会解析地址
* @type boolean
* @defaultValue false
*/
geocode?: boolean | null,
/**
* 高精度定位超时时间(ms),指定时间内返回最高精度,该值3000ms以上高精度定位才有效果
* @defaultValue 3000
*/
highAccuracyExpireTime?: number | null,
/**
* 开启高精度定位
* @type boolean
* @defaultValue false
*/
isHighAccuracy?: boolean | null,
/**
* 接口调用成功的回调函数
*/
success?: GetLocationSuccessCallback | null,
/**
* 接口调用失败的回调函数
*/
fail?: GetLocationFailCallback | null,
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: GetLocationCompleteCallback | null
};
## 1.0.1(2023-10-23)
更新android自定义基座操作步骤
## 1.0.0(2023-09-11)
基于腾讯定位服务,实现uni.getLocation 获取定位功能
{
"id": "uni-getLocation-tencent",
"displayName": "uni-getLocation-tencent",
"version": "1.0.1",
"description": "基于腾讯定位服务,实现uni.getLocation 获取定位功能",
"keywords": [
"uni-getLocation-tencent"
],
"repository": "",
"engines": {
"HBuilderX": "^3.8.12"
},
"dcloudext": {
"type": "uts",
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "插件使用的 腾讯定位SDK会采集数据,详情可参考:https://lbs.qq.com/",
"permissions": "<!-- 通过GPS得到精确位置 -->\n\t<uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\"/>\n\t<!-- 通过网络得到粗略位置 -->\n\t<uses-permission android:name=\"android.permission.ACCESS_COARSE_LOCATION\"/>\n\t<!-- 访问网络,某些位置信息需要从网络服务器获取 -->\n\t<uses-permission android:name=\"android.permission.INTERNET\"/>\n\t<!-- 访问WiFi状态,需要WiFi信息用于网络定位 -->\n\t<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>\n\t<!-- 修改WiFi状态,发起WiFi扫描, 需要WiFi信息用于网络定位 -->\n\t<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>\n\t<!-- 访问网络状态, 检测网络的可用性,需要网络运营商相关信息用于网络定位 -->\n\t<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>\n\t<!-- 访问网络的变化, 需要某些信息用于网络定位 -->\n\t<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>\n\t<!-- 蓝牙扫描权限 -->\n\t<uses-permission android:name=\"android.permission.BLUETOOTH\"/>\n\t<uses-permission android:name=\"android.permission.BLUETOOTH_ADMIN\"/>\n\t<!-- 前台service权限 -->\n\t<uses-permission android:name=\"android.permission.FOREGROUND_SERVICE\"/>\n\t<!-- 后台定位权限 -->\n\t<uses-permission android:name=\"android.permission.ACCESS_BACKGROUND_LOCATION\"/>\n\t<!-- A-GPS辅助定位权限,方便GPS快速准确定位 -->\n\t<uses-permission android:name=\"android.permission.ACCESS_LOCATION_EXTRA_COMMANDS\"/>\n"
},
"npmurl": ""
},
"uni_modules": {
"uni-ext-api": {
"uni": [
"getLocation"
]
},
"dependencies": [],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"Vue": {
"vue2": "y",
"vue3": "y"
},
"App": {
"app-android": {
"minVersion": "19"
},
"app-ios": {
"minVersion": "9"
}
},
"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
# uts-tencentgeolocation腾讯定位插件使用文档
## Android 平台
1. 申请腾讯地图key
[申请网址](https://lbs.qq.com/mobile/androidMapSDK/developerGuide/getKey)
2. 配置key到插件中
修改项目根目录下 AndroidManifest.xml
`<meta-data android:name="TencentMapSDK" android:value="您申请的Key" />`
3. 制作自定义基座运行后生效
## iOS 平台
1.申请腾讯地图key
[申请网址](https://lbs.qq.com/mobile/androidMapSDK/developerGuide/getKey)
2.配置key到插件中
将申请的key配置到插件目录下 app-ios -> info.plist 中 TencentLBSAPIKey 对应的值
```xml
<key>TencentLBSAPIKey</key>
<string>您申请的Key</string>
```
3.配置访问位置权限描述信息
选中工程中的 manifest.json -> App权限配置 -> iOS隐私信息访问的许可描述,分别配置下列权限描述信息
- NSLocationAlwaysUsageDescription
- NSLocationWhenInUseUsageDescription
- NSLocationAlwaysAndWhenInUseUsageDescription
4.制作自定义基座运行后生效
## 相关开发文档
- [UTS 语法](https://uniapp.dcloud.net.cn/tutorial/syntax-uts.html)
- [UTS 原生插件](https://uniapp.dcloud.net.cn/plugin/uts-plugin.html)
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"
package="io.dcloud.nativeresouce">
<!--permissions-->
<!-- 通过GPS得到精确位置 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<!-- 通过网络得到粗略位置 -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<!-- 访问网络,某些位置信息需要从网络服务器获取 -->
<uses-permission android:name="android.permission.INTERNET"/>
<!-- 访问WiFi状态,需要WiFi信息用于网络定位 -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<!-- 修改WiFi状态,发起WiFi扫描, 需要WiFi信息用于网络定位 -->
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
<!-- 访问网络状态, 检测网络的可用性,需要网络运营商相关信息用于网络定位 -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<!-- 访问网络的变化, 需要某些信息用于网络定位 -->
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
<!-- 蓝牙扫描权限 -->
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<!-- 前台service权限 -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<!-- 后台定位权限 -->
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
<!-- A-GPS辅助定位权限,方便GPS快速准确定位 -->
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS"/>
</manifest>
{
"dependencies": [
"com.tencent.map.geolocation:TencentLocationSdk-openplatform:7.3.0"
],
"minSdkVersion": "19"
}
import {
UTSAndroid
} from "io.dcloud.uts";
import ActivityCompat from "androidx.core.app.ActivityCompat";
import Manifest from "android.Manifest";
import Looper from "android.os.Looper";
import TencentLocationManager from "com.tencent.map.geolocation.TencentLocationManager";
import TencentLocationListener from "com.tencent.map.geolocation.TencentLocationListener";
import TencentLocation from "com.tencent.map.geolocation.TencentLocation";
import TencentLocationRequest from "com.tencent.map.geolocation.TencentLocationRequest";
import PackageManager from "android.content.pm.PackageManager";
import Class from 'java.lang.Class';
import Exception from 'java.lang.Exception';
import { GetLocation, GetLocationOptions, GetLocationSuccess,GetLocationFail } from "../interface.uts"
export const getLocation : GetLocation = function (options : GetLocationOptions) {
if(!checkHasIntegration()){
// 当前没有集成腾讯sdk,提示需要打包
let ret = new UniError("uni-getLocation-tencent",-10,"需要打自定义基座");
options.fail?.(ret)
options.complete?.(ret)
return;
}
if (!checkLocationConfig()) {
let ret = new UniError("uni-getLocation-tencent",-20,"未通过配置预校验,通常是app key 配置错误");
options.fail?.(ret)
options.complete?.(ret)
return;
}
/**
* 准备权限
*/
let permissionNeed = ["android.permission.ACCESS_FINE_LOCATION"];
UTSAndroid.requestSystemPermission(UTSAndroid.getUniActivity()!, permissionNeed, function (allRight:boolean,_grantedList:string[]) {
if (allRight) {
// 交给目前的location 引擎,真实执行
getLocationImpl(options)
}
}, function (_doNotAskAgain:boolean,_grantedList:string[]) {
console.log("用户拒绝了部分权限:")
let ret = new UniError("uni-getLocation-tencent",-30,"permission missed.");
options.fail?.(ret)
options.complete?.(ret)
})
}
/****************************************内部功能实现****************************************************/
/**
* 定位监听结果包装类
*/
class LocationOptionsWapper {
hostOption : GetLocationOptions;
constructor(option : GetLocationOptions) {
this.hostOption = option
}
onLocationChanged(location : TencentLocation, _error : Int,
_reason : string) {
let ret : GetLocationSuccess = {
latitude: location.latitude,
longitude: location.longitude,
speed: 0,
accuracy: location.accuracy,
altitude: location.altitude,
verticalAccuracy: 0,
horizontalAccuracy: location.accuracy,
address: location.address
}
this.hostOption.success?.(ret)
// 包装数据结构返回
}
onStatusUpdate(_name : string, _status : Int, _desc : string) {
// 定位状态发生变化
}
};
/**
* Tencent 定位监听实现类
*/
class SingleLocationListener extends TencentLocationListener {
hostOptionWraper : LocationOptionsWapper;
constructor(option : LocationOptionsWapper) {
super();
this.hostOptionWraper = option
}
override onLocationChanged(location : TencentLocation, error : Int,
reason : string) : void {
this.hostOptionWraper.onLocationChanged(location, error, reason);
}
override onStatusUpdate(name : string, status : Int, desc : string) : void {
this.hostOptionWraper.onStatusUpdate(name, status, desc);
}
}
/**
* 判断当前的基座是否已经集成了sdk, 即是否是自定义基座
*/
function checkHasIntegration() : boolean {
let hasIntegration = true
try {
let xClass = Class.forName("com.tencent.map.geolocation.TencentLocationListener")
} catch (e : Exception) {
hasIntegration = false;
}
if (!hasIntegration) {
return false;
}
return true
}
/**
* 检查定位的相关配置是否正确
*/
function checkLocationConfig() : boolean {
let packageName = UTSAndroid.getAppContext()!.getPackageName();
let appInfo = UTSAndroid.getAppContext()!.getPackageManager()!.getApplicationInfo(packageName, PackageManager.GET_META_DATA)
let metaData = appInfo.metaData
if (metaData == null) {
return false;
}
let adId = metaData.getString("TencentMapSDK")
if (adId == null) {
return false;
}
let splitArray = adId!.split("-")
let keyCharNum = splitArray.size
if (keyCharNum > 5) {
// 存在超过5个-,说明是符合规则的appkey
return true;
}
// 不符合校验规则,打回
return false;
}
/**
* 腾讯地图获取定位信息
* 参考文档:https://lbs.qq.com/mobile/androidLocationSDK/androidGeoGuide/androidGeoAdapt
*/
function getLocationImpl(locationOptions : GetLocationOptions) {
if(locationOptions.type != null && locationOptions.type!.toUpperCase() != 'GCJ-02' && locationOptions.type!.toUpperCase() != 'GCJ02'){
// 腾讯定位只支持GCJ-02,如果不是则报错
let ret = new UniError("uni-getLocation-tencent",-1,"GCJ-02 support only.");
locationOptions.fail?.(ret)
locationOptions.complete?.(ret)
return
}
let mLocationManager = TencentLocationManager.getInstance(UTSAndroid.getAppContext());
// 定位监听器封装
let locationOptionWrapper = new LocationOptionsWapper(locationOptions);
let mLocationListener = new SingleLocationListener(locationOptionWrapper);
// 发起单次请求
let locationRequest = TencentLocationRequest.create()
// 是否需要逆地理编码
if (locationOptions.geocode != null && locationOptions.geocode == true) {
locationRequest.setRequestLevel(TencentLocationRequest.REQUEST_LEVEL_NAME);
} else {
locationRequest.setRequestLevel(TencentLocationRequest.REQUEST_LEVEL_GEO);
}
// 是否开启了高精度
if (locationOptions.isHighAccuracy != null && locationOptions.isHighAccuracy == true) {
locationRequest.setAllowGPS(true)
}
/**
* 高度信息,腾讯没有明确的api设置
*/
if (locationOptions.altitude != null && locationOptions.altitude == true) {
locationRequest.setAllowGPS(true)
}
mLocationManager.requestSingleFreshLocation(locationRequest, mLocationListener, Looper.getMainLooper());
}
{
"deploymentTarget": "9"
}
\ No newline at end of file
export interface Uni {
/**
* 获取当前的地理位置、速度
*
* @tutorial http://uniapp.dcloud.io/api/location/location?id=getlocation
*/
getLocation(options: GetLocationOptions) : void;
}
export type GetLocation = (options: GetLocationOptions) => void;
export type GetLocationSuccess = {
/**
* 纬度,浮点数,范围为-90~90,负数表示南纬
*/
latitude: number,
/**
* 经度,范围为-180~180,负数表示西经
*/
longitude: number,
/**
* 速度,浮点数,单位m/s
*/
speed: number,
/**
* 位置的精确度
*/
accuracy: number,
/**
* 高度,单位 m
*/
altitude: number,
/**
* 垂直精度,单位 m(Android 无法获取,返回 0)
*/
verticalAccuracy: number,
/**
* 水平精度,单位 m
*/
horizontalAccuracy: number,
/**
* 地址信息
*/
address: any | null
};
type GetLocationSuccessCallback = (result: GetLocationSuccess) => void;
type GetLocationFailCallback = (result: UniError) => void;
type GetLocationComplete = any;
type GetLocationCompleteCallback = (result: GetLocationComplete) => void;
export type GetLocationOptions = {
/**
* 默认为 wgs84 返回 gps 坐标,gcj02 返回可用于uni.openLocation的坐标
*/
type?: string | null,
/**
* 传入 true 会返回高度信息,由于获取高度需要较高精确度,会减慢接口返回速度
* @type boolean
*/
altitude?: boolean | null,
/**
* 传入 true 会解析地址
* @type boolean
*/
geocode?: boolean | null,
/**
* 高精度定位超时时间(ms),指定时间内返回最高精度,该值3000ms以上高精度定位才有效果
*/
highAccuracyExpireTime?: number | null,
/**
* 开启高精度定位
* @type boolean
*/
isHighAccuracy?: boolean | null,
/**
* 接口调用成功的回调函数
*/
success?: GetLocationSuccessCallback | null,
/**
* 接口调用失败的回调函数
*/
fail?: GetLocationFailCallback | null,
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: GetLocationCompleteCallback | null
};
{
"id": "uni-getNetworkType",
"displayName": "uni-getNetworkType",
"version": "1.0.0",
"description": "uni-getNetworkType",
"keywords": [
"uni-getNetworkType"
],
"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": {
"getNetworkType": {
"name": "getNetworkType",
"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-getNetworkType
### 开发文档
[UTS 语法](https://uniapp.dcloud.net.cn/tutorial/syntax-uts.html)
[UTS API插件](https://uniapp.dcloud.net.cn/plugin/uts-plugin.html)
[UTS 组件插件](https://uniapp.dcloud.net.cn/plugin/uts-component.html)
[Hello UTS](https://gitcode.net/dcloud/hello-uts)
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"
package="io.dcloud.uni.getNetworkType">
<!--permissions-->
<!-- 访问网络状态 -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
</manifest>
import { GetNetworkTypeOptions, GetNetworkType, GetNetworkTypeSuccess } from "../interface.uts";
import UTSAndroid from 'io.dcloud.uts.UTSAndroid';
import Context from 'android.content.Context';
import ConnectivityManager from 'android.net.ConnectivityManager';
import TelephonyManager from 'android.telephony.TelephonyManager';
import Build from 'android.os.Build';
export const getNetworkType : GetNetworkType = function (options : GetNetworkTypeOptions) {
const context = UTSAndroid.getUniActivity()!!;
const connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager;
if (connectivityManager != null) {
if (Build.VERSION.SDK_INT >= 23) {
const permissions = ["android.permission.ACCESS_NETWORK_STATE"];
if (!UTSAndroid.checkSystemPermissionGranted(context, permissions)) {
const result : GetNetworkTypeSuccess = {
networkType: "none"
}
options?.success?.(result);
options?.complete?.(result);
return
}
}
const activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
if (activeNetworkInfo != null) {
if (activeNetworkInfo.getType() == ConnectivityManager.TYPE_WIFI) {
const result : GetNetworkTypeSuccess = {
networkType: "wifi"
}
options?.success?.(result);
options?.complete?.(result);
} else if (activeNetworkInfo.getType() == ConnectivityManager.TYPE_MOBILE) {
let type = "unknown";
const subtype = activeNetworkInfo.getSubtype();
switch (subtype) {
case TelephonyManager.NETWORK_TYPE_CDMA:
case TelephonyManager.NETWORK_TYPE_EDGE:
case TelephonyManager.NETWORK_TYPE_GPRS:
case 7://电信2g 努比亚
type = "2g";
break;
case TelephonyManager.NETWORK_TYPE_EVDO_0:
case TelephonyManager.NETWORK_TYPE_EVDO_A:
case 12://level9以上支持 TelephonyManager.NETWORK_TYPE_EVDO_B = 12
case 14://电信 努比亚
//3G 电信
type = "3g";
break;
case TelephonyManager.NETWORK_TYPE_HSDPA:
case TelephonyManager.NETWORK_TYPE_UMTS:
//3G 联通
type = "3g";
break;
case 17:
case 18:
//3G 移动(目前华为系统切换到3g时候为此值)
type = "3g";
break;
case 13: //level11 以上支持TelephonyManager.NETWORK_TYPE_LTE = 13
case 11: //level8以上支持TelephonyManager.NETWORK_TYPE_IDEN=11
case TelephonyManager.NETWORK_TYPE_HSUPA:
case TelephonyManager.NETWORK_TYPE_HSPA:
case 15://stype == TelephonyManager.NETWORK_TYPE_HSPAP
type = "4g";
break;
case TelephonyManager.NETWORK_TYPE_NR: {
type = "5g";
break;
}
default://对于case之外的反馈到js,js层收集之后回馈5+进行填补完善
type = "" + subtype;
break;
}
const result : GetNetworkTypeSuccess = {
networkType: type
}
options?.success?.(result);
options?.complete?.(result);
} else {
const result : GetNetworkTypeSuccess = {
networkType: "unknown"
}
options?.success?.(result);
options?.complete?.(result);
}
}else{
const result : GetNetworkTypeSuccess = {
networkType: "none"
}
options?.success?.(result);
options?.complete?.(result);
}
} else {
const result : GetNetworkTypeSuccess = {
networkType: "none"
}
options?.success?.(result);
options?.complete?.(result);
}
};
\ No newline at end of file
export interface Uni {
/**
* getNetworkType()
* @description
* 获取网络类型
* @param {GetNetworkTypeOptions} options
* @return {void}
* @tutorial http://uniapp.dcloud.io/api/system/network?id=getnetworktype
* @uniPlatform {
* "app": {
* "android": {
* "osVer": "4.4",
* "uniVer": "√",
* "unixVer": "3.9+"
* },
* "ios": {
* "osVer": "9.0",
* "uniVer": "√",
* "unixVer": "x"
* }
* }
* }
* @example
```typescript
uni.getNetworkType({
success(res){
console.log(res);
}
});
```
*/
getNetworkType(options: GetNetworkTypeOptions): void;
}
export type GetNetworkType = (options: GetNetworkTypeOptions) => void;
export type GetNetworkTypeSuccess = {
/**
* 网络类型
*/
networkType: string
};
export type GetNetworkTypeSuccessCallback = (result: GetNetworkTypeSuccess) => void;
export type GetNetworkTypeFail = UniError;
export type GetNetworkTypeFailCallback = (result: GetNetworkTypeFail) => void;
export type GetNetworkTypeComplete = any;
export type GetNetworkTypeCompleteCallback = (result: GetNetworkTypeComplete) => void;
export type GetNetworkTypeOptions = {
/**
* 接口调用成功的回调函数
* @defaultValue null
*/
success?: GetNetworkTypeSuccessCallback | null,
/**
* 接口调用失败的回调函数
* @defaultValue null
*/
fail?: GetNetworkTypeFailCallback | null,
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
* @defaultValue null
*/
complete?: GetNetworkTypeCompleteCallback | null
};
{
"id": "uni-getSystemInfo",
"displayName": "uni-getSystemInfo",
"version": "1.0.0",
"description": "uni-getSystemInfo",
"keywords": [
"uni-getSystemInfo"
],
"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": {
"getSystemInfo": {
"name": "getSystemInfo",
"app": {
"js": false,
"kotlin": true,
"swift": false
}
},
"getSystemInfoSync":{
"name": "getSystemInfoSync",
"app": {
"js": false,
"kotlin": true,
"swift": false
}
},
"getWindowInfo":{
"name": "getWindowInfo",
"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-getSystemInfo
### 开发文档
[UTS 语法](https://uniapp.dcloud.net.cn/tutorial/syntax-uts.html)
[UTS API插件](https://uniapp.dcloud.net.cn/plugin/uts-plugin.html)
[UTS 组件插件](https://uniapp.dcloud.net.cn/plugin/uts-component.html)
[Hello UTS](https://gitcode.net/dcloud/hello-uts)
\ No newline at end of file
import Activity from 'android.app.Activity';
import Configuration from 'android.content.res.Configuration';
import Context from 'android.content.Context';
import UiModeManager from 'android.app.UiModeManager';
import WindowManager from 'android.view.WindowManager';
import DisplayMetrics from 'android.util.DisplayMetrics';
import Build from 'android.os.Build';
import File from 'java.io.File';
import TextUtils from 'android.text.TextUtils';
import { UTSAndroid as Device } from "io.dcloud.uts";
import BufferedReader from 'java.io.BufferedReader';
import InputStreamReader from 'java.io.InputStreamReader';
import UTSAndroid from 'io.dcloud.uts.UTSAndroid';
export class DeviceUtil {
private static customOS : string | null = null
private static customOSVersion : string | null = null
private static readonly rootRelatedDirs = [
"/su", "/su/bin/su", "/sbin/su",
"/data/local/xbin/su", "/data/local/bin/su", "/data/local/su",
"/system/xbin/su",
"/system/bin/su", "/system/sd/xbin/su", "/system/bin/failsafe/su",
"/system/bin/cufsdosck", "/system/xbin/cufsdosck", "/system/bin/cufsmgr",
"/system/xbin/cufsmgr", "/system/bin/cufaevdd", "/system/xbin/cufaevdd",
"/system/bin/conbb", "/system/xbin/conbb"];
/**
* HarmonyOS 系统输出的
* 格式:2.0.0
*/
private static KEY_HARMONYOS_VERSION_NAME = "hw_sc.build.platform.version";
/**
* EMUI系统输出的
* 格式:EmotionUI_8.0.0
*/
private static KEY_EMUI_VERSION_NAME = "ro.build.version.emui";
/**
* MagicUI系统输出的
* 格式:3.1.0
*/
private static KEY_MAGICUI_VERSION = "ro.build.version.magic";
/**
* MIUI系统输出的
* 格式:V12
*/
private static KEY_MIUI_VERSION_NAME = "ro.miui.ui.version.name";
/**
* OPPO手机ColorOS系统输出的
* 格式:9
*/
private static KEY_COLOROS_VERSION_NAME = "ro.build.version.opporom";
/**
* VIVO手机系统输出的
* name格式:funtouch
* version格式: 9
*/
private static KEY_VIVO_VERSION_NAME = "ro.vivo.os.name";
private static KEY_VIVO_VERSION = "ro.vivo.os.version";
/**
* OonPlus手机系统输出的
* 格式:Hydrogen OS 11.0.7.10.KB05
*/
private static KEY_ONEPLUS_VERSION_NAME = "ro.rom.version";
/**
* 魅族手机系统输出的
*/
private static KEY_FLYME_VERSION_NAME = "ro.build.display.id";
/**
* nubia手机系统输出的
*/
private static KEY_NUBIA_VERSION_NAME = "ro.build.nubia.rom.name";
private static KEY_NUBIA_VERSION_CODE = "ro.build.nubia.rom.code";
public static getOrientation(activity : Activity) : string {
const activityOrientation = activity.getResources().getConfiguration().orientation;
let outOrientation = "portrait";
if (activityOrientation == Configuration.ORIENTATION_LANDSCAPE) {
outOrientation = "landscape";
}
return outOrientation;
}
public static getAppVersionCode():number{
const activity = UTSAndroid.getUniActivity()!!;
const packageInfo = activity.getPackageManager().getPackageInfo(activity.getPackageName(), 0);
return packageInfo.versionCode;
}
/**
* 获取屏幕像素比
*/
public static getScaledDensity(activity : Activity) : number {
const windowManager = activity.getSystemService(Context.WINDOW_SERVICE) as WindowManager;
const displayMetrics = new DisplayMetrics();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
windowManager.getDefaultDisplay().getRealMetrics(displayMetrics);
} else {
windowManager.getDefaultDisplay().getMetrics(displayMetrics);
}
return displayMetrics.scaledDensity;
}
public static getScreenWidth() : number {
return UTSAndroid.getScreenInfo()["screenWidth"] as Int;
}
public static getScreenHeight() : number {
return UTSAndroid.getScreenInfo()["screenHeight"] as Int;
}
public static getStatusBarHeight():number {
return UTSAndroid.getStatusBarHeight();
}
public static getRomName():string{
DeviceUtil.setCustomInfo(Build.MANUFACTURER);
return DeviceUtil.customOS ?? "";
}
public static getRomVersion():string{
DeviceUtil.setCustomInfo(Build.MANUFACTURER);
return DeviceUtil.customOSVersion ?? "";
}
public static getSystemUIModeType(activity : Activity) : string {
let uiModeManager = activity.getSystemService(Context.UI_MODE_SERVICE) as UiModeManager;
let modeType = "unknown";
switch (uiModeManager.getCurrentModeType()) {
case Configuration.UI_MODE_TYPE_TELEVISION:
modeType = "tv";
break;
case Configuration.UI_MODE_TYPE_WATCH:
modeType = "watch";
break;
case Configuration.UI_MODE_TYPE_NORMAL:
if (DeviceUtil.isTablet(activity)) {
modeType = "pad";
} else {
modeType = "phone";
}
break;
case Configuration.UI_MODE_TYPE_DESK:
modeType = "pc";
break;
case Configuration.UI_MODE_TYPE_UNDEFINED:
modeType = "undefined";
break;
case Configuration.UI_MODE_TYPE_CAR:
modeType = "car";
break;
case Configuration.UI_MODE_TYPE_VR_HEADSET:
modeType = "vr";
break;
case Configuration.UI_MODE_TYPE_APPLIANCE:
modeType = "appliance";
break;
}
return modeType;
}
public static getOsLanguageNormal(context : Context) : string {
const LOCALE_ZH_HANS = 'zh-Hans'
const LOCALE_ZH_HANT = 'zh-Hant'
let locale = Device.getLanguageInfo(context)["appLanguage"].toString();
if (locale.indexOf('zh') === 0) {
if (locale.indexOf('-hans') > -1) {
return LOCALE_ZH_HANS;
}
if (locale.indexOf('-hant') > -1) {
return LOCALE_ZH_HANT;
}
if (locale.includes("-tw") || locale.includes("-hk") || locale.includes("-mo") || locale.includes("-cht")) {
return LOCALE_ZH_HANT;
}
return LOCALE_ZH_HANS;
} else {
return locale;
}
}
/**
* 是否为平板 不是太准确
*/
public static isTablet(activity : Activity) : boolean {
return (activity.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_LARGE;
}
private static setCustomInfo(phoneBrand : string) {
try {
switch (DeviceUtil.deleteSpaceAndToUpperCase(phoneBrand)) {
case "HUAWEI":
if (DeviceUtil.isHarmonyOS()) {
DeviceUtil.customOSVersion = DeviceUtil.getSystemPropertyValue(DeviceUtil.KEY_HARMONYOS_VERSION_NAME);
DeviceUtil.customOS = "HarmonyOS";
} else {
DeviceUtil.customOS = "EMUI";
DeviceUtil.customOSVersion = DeviceUtil.getSystemPropertyValue(DeviceUtil.KEY_EMUI_VERSION_NAME);;
}
break;
case "HONOR":
if (DeviceUtil.isHarmonyOS()) {
DeviceUtil.customOS = "HarmonyOS";
if (!TextUtils.isEmpty(DeviceUtil.getSystemPropertyValue(DeviceUtil.KEY_HARMONYOS_VERSION_NAME))) {
DeviceUtil.customOSVersion = DeviceUtil.getSystemPropertyValue(DeviceUtil.KEY_HARMONYOS_VERSION_NAME);;
} else {
DeviceUtil.customOSVersion = "";
}
} else if (!TextUtils.isEmpty(DeviceUtil.getSystemPropertyValue(DeviceUtil.KEY_MAGICUI_VERSION))) {
DeviceUtil.customOS = "MagicUI";
DeviceUtil.customOSVersion = DeviceUtil.getSystemPropertyValue(DeviceUtil.KEY_MAGICUI_VERSION);
} else {
//格式:EmotionUI_8.0.0
DeviceUtil.customOS = "EMUI";
DeviceUtil.customOSVersion = DeviceUtil.getSystemPropertyValue(DeviceUtil.KEY_EMUI_VERSION_NAME);
}
break;
case "XIAOMI":
case "REDMI":
//格式:MIUIV12
DeviceUtil.customOS = "MIUI";
DeviceUtil.customOSVersion = DeviceUtil.getSystemPropertyValue(DeviceUtil.KEY_MIUI_VERSION_NAME);
break;
case "REALME":
case "OPPO":
//格式:ColorOSV2.1
DeviceUtil.customOS = "ColorOS";
DeviceUtil.customOSVersion = DeviceUtil.getSystemPropertyValue(DeviceUtil.KEY_COLOROS_VERSION_NAME);
break;
case "VIVO":
//格式:Funtouch9
DeviceUtil.customOS = "Funtouch";
DeviceUtil.customOSVersion = DeviceUtil.getSystemPropertyValue(DeviceUtil.KEY_VIVO_VERSION);
break;
case "ONEPLUS":
//格式:Hydrogen OS 11.0.7.10.KB05
DeviceUtil.customOS = "HydrogenOS";
DeviceUtil.customOSVersion = DeviceUtil.getSystemPropertyValue(DeviceUtil.KEY_ONEPLUS_VERSION_NAME);
break;
case "MEIZU":
//格式:Flyme 6.3.5.1G
DeviceUtil.customOS = "Flyme";
DeviceUtil.customOSVersion = DeviceUtil.getSystemPropertyValue(DeviceUtil.KEY_FLYME_VERSION_NAME);
break;
case "NUBIA":
//格式:nubiaUIV3.0
DeviceUtil.customOS = DeviceUtil.getSystemPropertyValue(DeviceUtil.KEY_NUBIA_VERSION_NAME);
DeviceUtil.customOSVersion = DeviceUtil.getSystemPropertyValue(DeviceUtil.KEY_NUBIA_VERSION_CODE);
break;
default:
DeviceUtil.customOS = "Android";
DeviceUtil.customOSVersion = Build.VERSION.RELEASE;
break;
}
} catch (e : Exception) {
}
}
/**
* 判断是否是华为鸿蒙系统,能否识别荣耀鸿蒙未知
*
* @return
*/
private static isHarmonyOS() : boolean {
try {
let classType = Class.forName("com.huawei.system.BuildEx");
let getMethod = classType.getMethod("getOsBrand");
let value = getMethod.invoke(classType) as string;
return !TextUtils.isEmpty(value);
} catch (e : Exception) {
return false;
}
}
/**
* 删除字符串中的空格并全部转成大写
* @param str
* @return
*/
public static deleteSpaceAndToUpperCase(str : string | null) : string {
if (TextUtils.isEmpty(str)) {
return "";
}
return str!.replace(" ", "").toUpperCase();
}
private static getSystemPropertyValue(propName : string) : string | null {
let value : string | null = null;
let roSecureObj : any | null;
try {
// Class.forName("java.lang.String")
const method = Class.forName("android.os.SystemProperties").getMethod("get", Class.forName("java.lang.String"));
roSecureObj = method.invoke(null, propName);
if (roSecureObj != null) {
value = roSecureObj as string;
}
} catch (e : Exception) {
}
return value;
}
}
\ No newline at end of file
此差异已折叠。
此差异已折叠。
# uni-getSystemSetting
### 开发文档
[UTS 语法](https://uniapp.dcloud.net.cn/tutorial/syntax-uts.html)
[UTS 原生插件](https://uniapp.dcloud.net.cn/plugin/uts-plugin.html)
[Hello UTS](https://gitcode.net/dcloud/hello-uts/-/tree/dev)
\ No newline at end of file
import { UTSAndroid } from "io.dcloud.uts";
import { DeviceUtil } from './device/DeviceUtil.uts';
import { GetSystemSetting, GetSystemSettingResult } from '../interface.uts'
import Exception from 'java.lang.Exception';
export const getSystemSetting : GetSystemSetting = () : GetSystemSettingResult => {
let context = UTSAndroid.getAppContext();
let result : GetSystemSettingResult = {
deviceOrientation : DeviceUtil.deviceOrientation(context!),
locationEnabled : DeviceUtil.locationEnable(context!),
};
try {
let blueToothEnable = DeviceUtil.blueToothEnable(context!);
result.bluetoothEnabled = blueToothEnable;
} catch (e : Exception) {
result.bluetoothError = "Missing permissions required by BluetoothAdapter.isEnabled: android.permission.BLUETOOTH";
}
try {
result.wifiEnabled = DeviceUtil.wifiEnable(context!);
} catch (e : Exception) {
result.wifiError = "Missing permissions required by WifiManager.isWifiEnabled: android.permission.ACCESS_WIFI_STATE";
}
return result;
}
\ No newline at end of file
此差异已折叠。
## 1.3.1(2023-09-15)
app端适配使用UniError
## 1.3.0(2023-05-30)
新增 同步获取电量api
## 1.2.0(2022-10-17)
实现百度小程序/支付宝小程序/QQ小程序获取电量
## 1.1.0(2022-10-17)
实现ios平台获取电量
......
{
"deploymentTarget": "9"
}
\ No newline at end of file
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册