ToolView.ets 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668
  1. import TitleBar from './TitleBar'
  2. import mainViewModel, { MainViewModel } from '../viewmodel/MainViewModel';
  3. import ItemData from '../viewmodel/ItemData';
  4. import { promptAction, router, Scale } from '@kit.ArkUI';
  5. import { CommonConstants } from '../common/constants/CommonConstants';
  6. import { wifiManager } from '@kit.ConnectivityKit';
  7. import { AppUtil,
  8. LogUtil,
  9. NetworkUtil,
  10. PermissionUtil, PickerUtil,
  11. PreferencesUtil,
  12. RandomUtil,
  13. ScanUtil,
  14. StrUtil,
  15. ToastUtil } from '@pura/harmony-utils';
  16. import wifi from '@ohos.wifiManager'
  17. import Logger from '../common/util/Logger';
  18. import { common, Permissions, Want } from '@kit.AbilityKit';
  19. import { ErrorEvent } from '@kit.ArkTS';
  20. import { BusinessError } from '@kit.BasicServicesKit';
  21. import { picker } from '@kit.CoreFileKit';
  22. import { photoAccessHelper } from '@kit.MediaLibraryKit';
  23. import { PullToRefresh } from '@ohos/pulltorefresh';
  24. import { Utility } from '../common/util/Utility';
  25. import { AnimationHelper, DialogAction,DialogHelper } from '@pura/harmony-dialog';
  26. import { DialogUtil } from '@pura/harmony-utils';
  27. import { DrawerOptions } from '../dialog/DrawerOptions';
  28. import WifiType from '../viewmodel/WiFiType';
  29. const TAG = 'ToolView'
  30. interface GeneratedObjectLiteralInterface_1 {
  31. bundleName: string;
  32. abilityName: string;
  33. action: string;
  34. }
  35. @Preview
  36. @Component
  37. export struct ToolView{
  38. @State isListening: boolean = true; // 控制组件状态 true:开启水波纹 false:停止水波纹
  39. private linkedInfo: wifi.WifiLinkedInfo = null!
  40. @State isLinked: boolean = false
  41. @StorageLink('wifiList') wifiList: Array<wifi.WifiScanInfo> = []
  42. @State uriStr: string = ''
  43. @State scanResult: string = ''
  44. private scroller: Scroller = new Scroller();
  45. @State currentName: string = ''
  46. @State ssid: string = ''
  47. @State state:AnimationStatus = AnimationStatus.Initial
  48. @State textWifi:string ='未连接'
  49. @State count:number =0
  50. //连接、通讯历史记录
  51. @State msgHistory: string = ''
  52. @State titleBarModel: TitleBar.Model = new TitleBar.Model()
  53. .setLeftIcon(null)
  54. .setTitleTextStyle(FontStyle.Normal)
  55. .setTitleName("工具")
  56. .setTitleFontColor(Color.White)
  57. .setTitleBarBackground($r('app.color.title_bar_bg'))
  58. .setTitleBarBottomLineColor($r('app.color.title_bar_bg'))
  59. @State bundleName:string =''
  60. // 组件生命周期
  61. async aboutToAppear() {
  62. this.initDialogConfig()
  63. this.bundleName = await AppUtil.getBundleName()
  64. this.scan()
  65. // 启动监听
  66. this.addListener()
  67. console.info('LifeCycleComponent aboutToAppear');
  68. }
  69. initDialogConfig() {
  70. DialogHelper.setDefaultConfig((config) => {
  71. config.alignment = DialogAlignment.Center; //弹窗的对齐方式。
  72. config.offset = { dx: 0, dy: 0 }; //弹窗相对alignment所在位置的偏移量。默认值:{ dx: 0, dy: 0 }
  73. config.maskColor = 0x33000000; //自定义蒙层颜色。默认值 0x33000000
  74. config.backgroundColor = $r('app.color.pri_bg'); //弹窗背板颜色。默认值:Color.White
  75. config.backgroundBlurStyle = BlurStyle.NONE; //弹窗背板模糊材质。默认值:BlurStyle.COMPONENT_ULTRA_THICK
  76. config.cornerRadius = 20; //设置背板的圆角半径。可分别设置4个圆角的半径。
  77. })
  78. }
  79. // 组件消失生命周期
  80. aboutToDisappear() {
  81. console.info('LifeCycleComponent aboutToDisappear');
  82. }
  83. // 扫描wifi
  84. async scan() {
  85. }
  86. //当前连接wifi的info和名称
  87. async getLinkedInfo() {
  88. }
  89. // 监听wifi的变化
  90. addListener() {
  91. }
  92. //跳转到市场界面进行好评
  93. gotoHao(){
  94. const want: Want = {
  95. uri: `store://appgallery.huawei.com/app/detail?id=${this.bundleName}`
  96. };
  97. const context = getContext(this) as common.UIAbilityContext;
  98. context.startAbility(want).then(()=>{
  99. //拉起成功
  100. }).catch(()=>{
  101. // 拉起失败
  102. });
  103. }
  104. //好评的自定义内容
  105. @Builder
  106. customHaoPingBuilder(content: string) {
  107. Column() {
  108. Text(content)
  109. .fontColor(Color.White)
  110. .fontSize(16)
  111. .alignSelf(ItemAlign.Start)
  112. .fontColor(Color.White)
  113. .margin({bottom:15})
  114. .fontSize(16)
  115. Row(){
  116. Button('取消')
  117. .fontColor(Color.White)
  118. .linearGradient( { direction: GradientDirection.Right, colors:[['#ff37a0fc',0.0],['#67e667',0.5],['#f5856e',1.0]]})
  119. .height(50)
  120. .layoutWeight(1)
  121. .stateEffect(true)
  122. .margin({right:6})
  123. .onClick(()=>{
  124. DialogHelper.closeDialog('haoping'); //关闭弹框
  125. })
  126. Button('好评')
  127. .fontColor(Color.White)
  128. .linearGradient( { direction: GradientDirection.Right, colors:[['#ff37a0fc',0.0],['#67e667',0.5],['#f5856e',1.0]]})
  129. .layoutWeight(1)
  130. .height(50)
  131. .stateEffect(true)
  132. .margin({left:6})
  133. .onClick(()=>{
  134. DialogHelper.closeDialog('haoping'); //关闭弹框
  135. this.gotoHao()
  136. PreferencesUtil.putSync("is_haoping", true);
  137. })
  138. }
  139. }
  140. .width("100%")
  141. .padding(10)
  142. }
  143. showHaopingDialog(){
  144. DialogHelper.showCustomContentDialog({
  145. dialogId:'haoping',
  146. title: "该功能免费",
  147. autoCancel: false, //点击遮障层时,不关闭弹窗
  148. backCancel: true, //点击返回键,不关闭弹窗
  149. contentBuilder: () => {
  150. this.customHaoPingBuilder("如果您觉得好用可以给个好评吗?谢谢!\n给个好评吧,非常感谢您的支持!")
  151. },
  152. buttons: [],
  153. })
  154. }
  155. //自定义文本和图片
  156. @Builder
  157. customSeeBuilder(content: string) {
  158. Column() {
  159. Text(content)
  160. .fontColor(Color.White)
  161. .fontSize(16)
  162. // Text(){
  163. // Span('点我查看华为截屏教程')
  164. // .fontColor($r('app.color.white'))
  165. // .decoration({ type: TextDecorationType.Underline, color:$r('app.color.white') })
  166. // .onClick(()=>{
  167. // DialogHelper.closeDialog('dig'); //关闭弹框
  168. // router.pushUrl({url:'pages/WebIndex',
  169. // params:{ titleName:'截图教程',webUrl:$rawfile('jieping.html')}
  170. // },router.RouterMode.Single);
  171. //
  172. //
  173. // })
  174. // }
  175. // .alignSelf(ItemAlign.Start)
  176. // .fontColor(Color.White)
  177. // .visibility(Visibility.None)
  178. // .margin({bottom:15})
  179. // .fontSize(16)
  180. Row(){
  181. Button('1、截图')
  182. .fontColor(Color.White)
  183. .linearGradient( { direction: GradientDirection.Right, colors:[['#ff37a0fc',0.0],['#67e667',0.5],['#f5856e',1.0]]})
  184. .height(50)
  185. .layoutWeight(1)
  186. .stateEffect(true)
  187. .margin({right:6})
  188. .onClick(()=>{
  189. this.goSystemWifiSetting()
  190. })
  191. Button('2、选图')
  192. .fontColor(Color.White)
  193. .linearGradient( { direction: GradientDirection.Right, colors:[['#ff37a0fc',0.0],['#67e667',0.5],['#f5856e',1.0]]})
  194. .layoutWeight(1)
  195. .height(50)
  196. .stateEffect(true)
  197. .margin({left:6})
  198. .onClick(()=>{
  199. DialogHelper.closeDialog('dig'); //关闭弹框
  200. this.goSelectPhoto()
  201. })
  202. }
  203. }
  204. .width("100%")
  205. .padding(10)
  206. }
  207. async showSeePwdDialog(){
  208. if(Utility.isFreeTime()){
  209. let isHao:boolean = PreferencesUtil.getBooleanSync('is_haoping');
  210. if(!isHao){
  211. this.showHaopingDialog()
  212. return
  213. }
  214. }
  215. DialogHelper.showCustomContentDialog({
  216. dialogId:'dig',
  217. title: "提示:请按如下教程",
  218. contentBuilder: () => {
  219. this.customSeeBuilder("第一步:请点击【1、截图】按钮,去系统的WIFI设置界面点到wifi分享二维码界面,然后截图。\n\n第二步:点击【2、选图】按钮,选择该截图的图片进行wifi密码解析。\n")
  220. },
  221. buttons: [],
  222. })
  223. }
  224. showFileDialog() {
  225. let ps: Permissions = 'ohos.permission.READ_MEDIA';
  226. // let ps: Permissions[] = ['ohos.permission.READ_MEDIA'];
  227. PermissionUtil.checkPermissions(ps).then((result) => {
  228. if (result) {
  229. //有文件权限,直接调用第一步和第二部对话框
  230. this.showSeePwdDialog()
  231. } else {
  232. Logger.info(TAG, 'not file permissions state:')
  233. //没有文件权限
  234. // this.showRuqFile();
  235. }
  236. })
  237. }
  238. // async showRuqFile(){
  239. //
  240. //
  241. // DialogUtil.showPrimaryDialog({
  242. // backgroundColor:$r('app.color.btn_green'),
  243. // title: "申请文件权限",
  244. // message: '此功能需要读取相册截图的WiFi的二维码图片,从而解析出当前wifi连接的密码。所以需要向您申请文件存储权限,如果紧急将无法使用该功能。\n',
  245. // borderStyle:BorderStyle.Dashed,
  246. // primaryButton: {
  247. // backgroundColor:$r('app.color.btn_green'),
  248. // value: "取消申请",
  249. // action: () => {
  250. //
  251. // }
  252. // },
  253. // secondaryButton: {
  254. // backgroundColor:$r('app.color.btn_red'),
  255. // value: "现在申请",
  256. // action: () => {
  257. // let ps: Permissions[] = ['ohos.permission.READ_MEDIA', 'ohos.permission.WRITE_MEDIA'];
  258. // PermissionUtil.requestPermissions(ps).then((result) => {
  259. // if (result) {
  260. // this.showSeePwdDialog()
  261. // } else {
  262. // ToastUtil.showLong("请在设置中打开权限")
  263. // // AppUtil.toAppSetting()
  264. // }
  265. // })
  266. // }
  267. // },
  268. // onWillDismiss: (dismissDialogAction: DismissDialogAction) => {
  269. // LogUtil.error("showPrimaryDialog-onWillDismiss: " + JSON.stringify(dismissDialogAction))
  270. // if (dismissDialogAction.reason == DismissReason.PRESS_BACK) {
  271. // dismissDialogAction.dismiss()
  272. // }
  273. // if (dismissDialogAction.reason == DismissReason.TOUCH_OUTSIDE) {
  274. // dismissDialogAction.dismiss()
  275. // }
  276. // }
  277. // })
  278. // }
  279. //拉起相册的选择刚刚截图的二维码图片进行扫描解析密码
  280. goSelectPhoto(){
  281. let options = new photoAccessHelper.PhotoSelectOptions();
  282. options.maxSelectNumber = 1;
  283. options.MIMEType =photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE;
  284. //调用系统的相册
  285. // PickerUtil.selectPhoto(options).then((uris) => {
  286. // this.uriStr = uris[0];
  287. //
  288. // Logger.info(TAG, 'select photo uri:' + uris[0])
  289. // //获得二维码图片uri用scan进行扫描
  290. // ScanUtil.onDetectBarCode(uris[0]).then((scanResult)=>{
  291. //
  292. // this.showPwdResultDialog(scanResult[0].originalValue);
  293. // Logger.info(TAG, 'scan select photo result:' + scanResult[0].originalValue)
  294. // // Logger.info(TAG, 'scan select photo result:' +JSON.stringify(scanResult, null, 2))
  295. // }).catch((err: BusinessError) => {
  296. // this.uriStr = `扫描二维码异常:\n${JSON.stringify(err)}`
  297. // })
  298. //
  299. // }).catch((err: BusinessError) => {
  300. // this.uriStr = `调用相册,异常:\n${JSON.stringify(err)}`
  301. // })
  302. }
  303. //自定义文本和图片
  304. @Builder
  305. customShowPwdBuilder(result: string) {
  306. Column() {
  307. Text('WiFi名称:'+getWiFiName(result)+'\n\nWiFi密码:'+getWiFiPWD(result)+'\n\n加密类型:WPA/WPA2\n')
  308. .fontColor(Color.White)
  309. .fontSize(16)
  310. Row(){
  311. Button('复制密码')
  312. .fontColor(Color.White)
  313. .linearGradient( { direction: GradientDirection.Right, colors:[['#ff37a0fc',0.0],['#67e667',0.5],['#f5856e',1.0]]})
  314. .height(50)
  315. .layoutWeight(1)
  316. .stateEffect(true)
  317. .onClick(()=>{
  318. Utility.copyText(getWiFiPWD(result))
  319. ToastUtil.showToast('复制成功')
  320. DialogHelper.closeDialog('pwd')
  321. })
  322. }
  323. }
  324. .width("100%")
  325. .padding(10)
  326. }
  327. //解析二维码的密码的对话框
  328. showPwdResultDialog(result:string){
  329. DialogHelper.showCustomContentDialog({
  330. dialogId:'pwd',
  331. title: "WiFi详情",
  332. contentBuilder: () => {
  333. this.customShowPwdBuilder(result)
  334. },
  335. buttons: [],
  336. })
  337. }
  338. //跳转到系统wifi界面
  339. goSystemWifiSetting(){
  340. let context = getContext(this) as common.UIAbilityContext;
  341. let want: Want = {
  342. bundleName: 'com.huawei.hmos.settings',
  343. abilityName: 'com.huawei.hmos.settings.MainAbility',
  344. uri: 'wifi_entry'};
  345. context.startAbility(want)
  346. .then(() => {
  347. // ...
  348. })
  349. .catch((err:Error) => {
  350. console.error(`Failed to startAbility. Code: ${err.name}, message: ${err.message}`);
  351. });
  352. }
  353. build() {
  354. Scroll(){
  355. Column() {
  356. TitleBar({ model: $titleBarModel })
  357. Column() {
  358. Shape() {
  359. Ellipse()
  360. .height(200)
  361. .width('100%')
  362. .fill(Color.White)
  363. .backgroundColor($r('app.color.title_bar_bg'))
  364. }
  365. }
  366. .width('100%')
  367. .height(100)
  368. .alignItems(HorizontalAlign.Start)
  369. .borderRadius({ bottomLeft: 20, bottomRight: 20 })
  370. Stack() {
  371. Column() {
  372. Grid() {
  373. ForEach(mainViewModel.getWiFiGridData(), (item: ItemData) => {
  374. GridItem() {
  375. Column() {
  376. Image(item.img)
  377. .width(38)
  378. .height(38)
  379. .margin({top:22})
  380. .alignSelf(ItemAlign.Center)
  381. .visibility(item.isHide ? Visibility.None : Visibility.Visible)
  382. Text(item.title)
  383. .fontSize(12)
  384. .fontWeight(300)
  385. .fontColor(Color.Grey)
  386. .margin({ top: 8 })
  387. .visibility(item.isHide ? Visibility.None : Visibility.Visible)
  388. }
  389. // .backgroundImage($r('app.media.circle'))
  390. .backgroundImagePosition(Alignment.Top)
  391. .backgroundImageSize({width:100,height:100})
  392. .height('100%')
  393. .width('100%')
  394. .onClick(() => {
  395. switch (item.id) {
  396. case MainViewModel.SAFE_TEST:
  397. router.pushUrl({url:'pages/SafeTestIndex'
  398. });
  399. break
  400. case MainViewModel.SEE_PWD:
  401. // this.showFileDialog()
  402. this.showSeePwdDialog() //鸿蒙系统不需要申请文件权限
  403. break
  404. case MainViewModel.SPEED_TEST:
  405. // router.pushUrl({url:'pages/WebPage',
  406. // params:{ titleName:'网络测速',webUrl:CommonConstants.IS_YUN_CESU2}
  407. // });
  408. router.pushUrl({
  409. url: 'pages/SpeedIndex'
  410. });
  411. break
  412. case MainViewModel.JIAO_CHENG:
  413. router.pushUrl({
  414. url: 'pages/MacPage'
  415. });
  416. break
  417. case MainViewModel.CAMERA_TEST:
  418. router.pushUrl({
  419. url: 'pages/AddSpeedPage'
  420. });
  421. break
  422. case MainViewModel.POWER_TEST:
  423. //跳转到系统的省电模式
  424. router.pushUrl({
  425. url: 'pages/CoolingPage'
  426. });
  427. break
  428. }
  429. })
  430. }
  431. })
  432. }
  433. .columnsTemplate('1fr 1fr 1fr')
  434. .rowsTemplate('1fr 1fr')
  435. .height(230)
  436. .borderRadius(24)
  437. .margin({top:50})
  438. }
  439. }
  440. // Column() {
  441. // Line().width('100%').height(0.5).backgroundColor($r('app.color.index_tab_unselected_font_color'))
  442. // Text(this.textWifi)
  443. // .fontSize(13)
  444. // .fontColor($r('app.color.title_bar_bg'))
  445. // .alignSelf(ItemAlign.Start)
  446. // .margin({ left: 15 })
  447. // .height(38)
  448. // .backgroundColor(Color.White)
  449. // Line().width('100%').height(1).backgroundColor($r('app.color.title_bar_bg'))
  450. //
  451. // }
  452. // .layoutWeight(1)
  453. }
  454. .width('100%')
  455. .height('100%')
  456. .backgroundColor(Color.White)
  457. }
  458. .height(1024)
  459. }
  460. /**
  461. * 查看密码的dialgo定布局提示弹窗
  462. */
  463. @Builder
  464. builderCustomDialogTipView() {
  465. Column() {
  466. Column({ space: '10vp' }) {
  467. Text('提示:请按如下教程')
  468. .fontSize('15fp')
  469. .fontColor(Color.Black)
  470. .textAlign(TextAlign.Start)
  471. .fontWeight(500)
  472. Text('第一步:点击第一步按钮,去系统的WIFI设置界面点到wifi分享二维码界面,然后截图。\n\n第二步:点击第二步按钮,选择该截图的图片进行wifi密码解析。\n')
  473. .fontSize('15fp')
  474. .fontColor(Color.Grey)
  475. .textAlign(TextAlign.Start)
  476. .fontWeight(FontWeight.Regular)
  477. .margin({left:8,right:8})
  478. .padding(5)
  479. Row() {
  480. Button('第一步', { type: ButtonType.Normal, stateEffect: true })
  481. .fontColor(Color.White)
  482. .fontSize('13fp')
  483. .width('50%')
  484. .backgroundColor('#55ceac')
  485. .onClick(() => {
  486. this.goSystemWifiSetting()
  487. })
  488. .borderRadius({
  489. bottomLeft: '5vp',
  490. })
  491. Button('第二步', { type: ButtonType.Normal, stateEffect: true })
  492. .fontColor(Color.White)
  493. .fontSize('13fp')
  494. .width('50%')
  495. .backgroundColor('#ff6b47')
  496. .onClick(() => {
  497. this.goSelectPhoto()
  498. })
  499. .borderRadius({
  500. bottomRight: '5vp'
  501. })
  502. }
  503. .justifyContent(FlexAlign.SpaceBetween)
  504. .width("100%")
  505. .borderRadius({
  506. bottomLeft: '5vp',
  507. bottomRight: '5vp'
  508. })
  509. }
  510. .alignItems(HorizontalAlign.Center)
  511. .width('100%')
  512. .backgroundColor(Color.White)
  513. .borderRadius('5vp')
  514. .margin({
  515. top: '15vp'
  516. })
  517. }
  518. .width('100%')
  519. .borderRadius('5vp')
  520. .backgroundColor(Color.White)
  521. }
  522. }
  523. //根据 WIFI:T:WPA;S:Tenda_xiaoke;P:20161221;; 解析出wifi的名称
  524. function getWiFiName(res: string): string {
  525. let str =''
  526. if(StrUtil.isNotEmpty(res)){
  527. if(res.indexOf('S:')!=-1){
  528. str = res.substring(res.indexOf('S:')+2,res.indexOf(';P:'))
  529. }
  530. }
  531. return str
  532. }
  533. //根据 WIFI:T:WPA;S:Tenda_xiaoke;P:20161221;; 解析出wifi的密码
  534. function getWiFiPWD(res: string): string {
  535. let str =''
  536. if(StrUtil.isNotEmpty(res)){
  537. if(res.indexOf('P:')!=-1){
  538. str = res.substring(res.indexOf('P:')+2,res.indexOf(';;'))
  539. }
  540. }
  541. return str
  542. }