小工具知识网

当前位置: 首页 > 行业知识 > WanAndroid(鸿蒙版)开发的第一篇

行业知识

WanAndroid(鸿蒙版)开发的第一篇

2026-11-04 15:51:43 来源:互联网转载

前言

DevEco Studio版本:4.0.0.600

WanAndroid的API链接:玩Android 开放API-玩Android - wanandroid.com

为了兼容HarmonyOS,我这边以Arkts--API9为例进行实现

通过华为官网渠道目前下载的版本还是3.1的,这边提供下4.0版本下载的渠道:

 DevEco Studio 4.0版本下载地址:DevEcoStudio 4.0版本下载

4.0版本的配套关系

注:一些基础知识点和默认配置项不做详细说明了,本文基于大家有一定的鸿蒙基础能力。有不明白的可以留言咨询

实现效果:

玩安卓演示视频

项目创建

为了兼容HarmonyOS(目前手机API版本只到9),compile SDK : 9

模块构建

根据项目功能模块划分了:HomeModule、ProjectModule、NavigationModule、MineModule四个功能模块,加上基础模块BaseLibrary和主模块entry组成项目的基础架构。

File-->new-->Module新建模块

其他几个模块依照上图为例依次创建,创建后如下图所示:

BaseLibrary资源链接:https://download.csdn.net/download/Abner_Crazy/88908326

项目页面实现

1、启动页面(SplashPage)

新建SplashPage页面:new-->Page创建页面,或者new-->ArkTS File创建文件(需要手动在main_pages.json中添加页面引用)

SplashPage详细代码:

import router from '@ohos.router'import LogUtils from '@app/BaseLibrary/src/main/ets/utils/LogUtils'@Entry@Componentstruct SplashPage {   @State counter: number = 5   @State message: string = 'Wan Android'   private intervalID: number = -1   build() {      RelativeContainer() {         Text(this.message)            .fontSize(52)            .fontWeight(FontWeight.Bold)            .id('textContent')            .alignRules({               center: { anchor: '__container__', align: VerticalAlign.Center },                middle: { anchor: '__container__', align: HorizontalAlign.Center }            })         //倒计时         Text(`${this.counter}s后跳转`)            .fontSize(15)            .fontColor(Color.Gray)            .id('textJump')            .alignRules({               right: { anchor: '__container__', align: HorizontalAlign.End },               top: { anchor: '__container__', align: VerticalAlign.Top }            })            .padding({ left: 10, right: 10, top: 5, bottom: 5 })            .margin({ top: 20, right: 20 })            .borderWidth(1)            .borderRadius(5)            .borderColor(Color.Gray)            .onClick(() => {               this.goIntent()            })      }      .width('100%')      .height('100%')      .onAppear(() => {         LogUtils.info('222222222  显示')         this.intervalID = setInterval(() => {            this.counter = this.counter - 1            if (this.counter == 0) {               clearInterval(this.intervalID)               this.goIntent()            }         }, 1000);      })      .onDisAppear(() => {         LogUtils.info('222222222  隐藏')         this.counter = 5         clearInterval(this.intervalID)      })   }   private goIntent(): void {      let userLoginStatus = false //TODO:获取登录状态,后面实现      if (userLoginStatus) {         router.replaceUrl({ url: 'pages/MainPage' })      } else {         router.replaceUrl({ url: 'pages/LoginPage' })      }   }}

2、登录页面(LoginPage)

LoginPage页面详细代码:

import { Constants, HttpManager, LoadingDialog, RequestMethod, UserManager } from "@app/BaseLibrary"import LogUtils from '@app/BaseLibrary/src/main/ets/utils/LogUtils'import { RegisterBean } from '../bean/RegisterBean'import promptAction from '@ohos.promptAction'import { LoginBean } from '../bean/LoginBean'import router from '@ohos.router'const TAG = 'LoginPage--- ';@Entry@Componentstruct LoginPage {   @State username: string = "" //用户名   @State password: string = "" //密码   hideJump: boolean = router.getParams()?.['hideJump']   build() {      RelativeContainer() {         Image($r("app.media.ic_back"))            .width(36)            .height(32)            .id('imageBack')            .margin(20)            .alignRules({               left: { anchor: '__container__', align: HorizontalAlign.Start },               top: { anchor: '__container__', align: VerticalAlign.Top }            })            .onClick(() => {               router.back()            })         if (!this.hideJump) {            Text('跳过')               .fontSize(15)               .fontColor(Color.Gray)               .id('textJump')               .alignRules({                  right: { anchor: '__container__', align: HorizontalAlign.End },                  top: { anchor: '__container__', align: VerticalAlign.Top }               })               .padding({ left: 10, right: 10, top: 5, bottom: 5 })               .margin({ top: 20, right: 20 })               .borderWidth(1)               .borderRadius(5)               .borderColor(Color.Gray)               .onClick(() => {                  router.clear()                  router.replaceUrl({ url: 'pages/MainPage' })               })         }         Text('登录')            .fontSize(50)            .fontColor(Color.Black)            .fontWeight(FontWeight.Bold)            .id('textLogin')            .margin({ top: 30 })            .alignRules({               middle: { anchor: '__container__', align: HorizontalAlign.Center },               top: { anchor: 'imageBack', align: VerticalAlign.Bottom }            })         //用户名和密码         Column() {            Row() {               Image($r('app.media.username'))                  .width(32)                  .height(32)               TextInput({ placeholder: '请输入用户名' })                  .width(300)                  .margin({ left: 16 })                  .onChange((value: string) => {                     this.username = value                  })            }            Row() {               Image($r('app.media.password'))                  .width(32)                  .height(32)               TextInput({ placeholder: '请输入密码' })                  .type(InputType.Password)                  .width(300)                  .margin({ left: 16 })                  .onChange((value: string) => {                     this.password = value                  })            }.margin({ top: 20 })         }.id('columnLogin')         .margin({ top: 80 })         .alignRules({            middle: { anchor: '__container__', align: HorizontalAlign.Center },            top: { anchor: 'textLogin', align: VerticalAlign.Bottom }         })         Button("注册")            .width(340)            .height(60)            .onClick(() => {               this.registerData()            })            .id('buttonLogin')            .margin({ bottom: 80 })            .alignRules({               middle: { anchor: '__container__', align: HorizontalAlign.Center },               bottom: { anchor: '__container__', align: VerticalAlign.Bottom }            })         Button("登录")            .width(340)            .height(60)            .onClick(() => {               this.dialogController.open()               this.loginData()            })            .id('buttonRegister')            .backgroundColor(Color.Pink)            .margin({ bottom: 40 })            .alignRules({               middle: { anchor: '__container__', align: HorizontalAlign.Center },               bottom: { anchor: 'buttonLogin', align: VerticalAlign.Top }            })      }      .width('100%')      .height('100%')   }   /**    * 登录请求    */   private loginData(): void {      if (this.username.trim().length == 0 || this.password.trim().length == 0) {         promptAction.showToast({ message: "用户名或密码不能为空" })         return      }      HttpManager.getInstance()         .request({            method: RequestMethod.POST,            header: { "Content-Type": "application/json" },            url: `https://www.wanandroid.com/user/login?username=${this.username}&password=${this.password}`, //wanAndroid的API:登录         })         .then((result: LoginBean) => {            this.dialogController.close()            LogUtils.info(TAG, "content  encodeURIComponent: " + encodeURIComponent(this.username) + "   result:" + JSON.stringify(result))            if (result.errorCode == 0) {               AppStorage.SetOrCreate(Constants.APPSTORAGE_ISLOGIN, true)               AppStorage.SetOrCreate(Constants.APPSTORAGE_USERNAME, encodeURIComponent(this.username))               AppStorage.SetOrCreate(Constants.APPSTORAGE_PASSWORD, this.password)               AppStorage.SetOrCreate(Constants.APPSTORAGE_TOKEN_PASS, this.cookiesMatch(JSON.stringify(result.header)))               promptAction.showToast({ message: "登录成功" })               UserManager.setLogIn(true)               router.clear()               router.replaceUrl({ url: 'pages/MainPage' })            } else {               promptAction.showToast({ message: result.errorMsg })            }         })         .catch((error) => {            this.dialogController.close()            promptAction.showToast({ message: "登录失败" })            LogUtils.info(TAG, "error: " + JSON.stringify(error))         })   }   /**    * 注册请求    */   private registerData(): void {      if (this.username.trim().length == 0 || this.password.trim().length == 0) {         promptAction.showToast({ message: "用户名或密码不能为空" })         return      }      HttpManager.getInstance()         .request({            method: RequestMethod.POST,            header: { "Content-Type": "application/json" },            url: `https://www.wanandroid.com/user/register?username=${this.username}&password=${this.password}&repassword=${this.password}`, //wanAndroid的API:注册         })         .then((result: RegisterBean) => {            LogUtils.info(TAG, "result: " + JSON.stringify(result))            if (result.errorCode == 0) {               promptAction.showToast({ message: "注册成功" })            } else {               promptAction.showToast({ message: result.errorMsg })            }         })         .catch((error) => {            promptAction.showToast({ message: "注册失败" })            LogUtils.info(TAG, "error: " + JSON.stringify(error))         })   }   /**    * cookies正则匹配,获取token_pass    * @returns    */   private cookiesMatch(header: string): string {      LogUtils.info(TAG, " cookiesMatch   header: " + header)      let content = header.match(/token_pass_wanandroid_com=(\S*);/)[1]      LogUtils.info(TAG, "  cookiesMatch  content: " + content)      return content   }   private dialogController = new CustomDialogController({      builder: LoadingDialog({ content: '登录中...' }),      customStyle: true,      alignment: DialogAlignment.Center, // 可设置dialog的对齐方式,设定显示在底部或中间等,默认为底部显示   })}

登录界面用到的HttpManager网络请求参考之前的文章:鸿蒙自定义Http网络访问组件-CSDN博客

登录成功后通过AppStorage保存登录状态:APPSTORAGE_ISLOGIN,用户名:APPSTORAGE_USERNAME(注:需要执行encodeURIComponent(this.username)进行编码,解决部分特殊用户名乱码问题),密码:APPSTORAGE_PASSWORD,用户登录后的token:APPSTORAGE_TOKEN_PASS(执行 cookiesMatch方法进行正则匹配)

AppStorage.SetOrCreate(Constants.APPSTORAGE_ISLOGIN, true)AppStorage.SetOrCreate(Constants.APPSTORAGE_USERNAME, encodeURIComponent(this.username))AppStorage.SetOrCreate(Constants.APPSTORAGE_PASSWORD, this.password)AppStorage.SetOrCreate(Constants.APPSTORAGE_TOKEN_PASS, this.cookiesMatch(JSON.stringify(result.header)))

3、主页面(MainPage)

MainPage页面详细代码:

import { Constants } from "@app/BaseLibrary"import LogUtils from "@app/BaseLibrary/src/main/ets/utils/LogUtils"import { MainTitleBar } from '../widget/MainTitleBar';@Entry@Componentstruct MainPage {   private tabsController: TabsController = new TabsController();   @State currentTabIndex: number = Constants.HOME_TAB_INDEX;   @State title: string = '首页'   @Builder   TabBuilder(title: string, index: number, normalIcon: Resource, selectIcon: Resource) {      Column() {         Image(this.currentTabIndex == index ? selectIcon : normalIcon)            .width(25)            .height(25)         Text(title)            .margin({ top: 4 })            .fontSize("10fp")            .fontColor(this.currentTabIndex == index ? "#1296db" : "#999999")      }      .justifyContent(FlexAlign.Center)      .height(56)      .width('100%')      .onClick(() => {         this.currentTabIndex = index;         this.tabsController.changeIndex(this.currentTabIndex)      })   }   build() {      Column() {         MainTitleBar({ title: this.title, showSearch: this.currentTabIndex == 0 })         Tabs({            barPosition: BarPosition.End,            controller: this.tabsController,         }) {            // 首页            TabContent() {               // HomePage()            }            .padding({ left: 12, right: 12 })            .tabBar(this.TabBuilder(Constants.HOME_TITLE, Constants.HOME_TAB_INDEX               , $r('app.media.ic_bottom_normal_home'), $r('app.media.ic_bottom_select_home')))            // 项目            TabContent() {               // ProjectPage()            }            .tabBar(this.TabBuilder(Constants.PROJECT_TITLE, Constants.PROJECT_TAB_INDEX               , $r('app.media.ic_bottom_normal_project'), $r('app.media.ic_bottom_select_project')))            // 导航            TabContent() {               // NavigationPage()            }            .padding({ left: 12, right: 12 })            .tabBar(this.TabBuilder(Constants.NAVIGATION_TITLE, Constants.NAVIGATION_TAB_INDEX               , $r('app.media.ic_bottom_normal_navigation'), $r('app.media.ic_bottom_select_navigation')))            //我的            TabContent() {               // MinePage()            }            .tabBar(this.TabBuilder(Constants.MINE_TITLE, Constants.MINE_TAB_INDEX               , $r('app.media.ic_bottom_normal_mine'), $r('app.media.ic_bottom_select_mine')))         }         .width('100%')         .height('100%')         .flexShrink(1)         .scrollable(false)         .animationDuration(100)         .barHeight(56)         .backgroundColor($r('app.color.bar_backgroundColor'))         .barMode(BarMode.Fixed)         .onChange((index: number) => {            this.title = this.getTitle(index)            this.currentTabIndex = index;         })      }.width('100%')      .height('100%')      .backgroundColor(Color.White)   }   private getTitle(index: number): string {      let titleList = [Constants.HOME_TITLE, Constants.PROJECT_TITLE, Constants.NAVIGATION_TITLE, Constants.MINE_TITLE]      LogUtils.info("3333333333333333  titleList: " + titleList[index])      return titleList[index]   }}
MainTitleBar详细代码:
import router from '@ohos.router'@Preview@Componentexport struct MainTitleBar {   @Prop title: string   @Prop showSearch: boolean   build() {      RelativeContainer() {         Text(this.title)            .fontSize(24)            .fontColor(Color.White)            .fontWeight(FontWeight.Bold)            .id("textTitle")            .alignRules({               center: { anchor: '__container__', align: VerticalAlign.Center },               middle: { anchor: '__container__', align: HorizontalAlign.Center }            })         Image($r('app.media.ic_search'))            .width(25)            .height(25)            .id("imageSearch")            .margin({ right: 16 })            .alignRules({               center: { anchor: '__container__', align: VerticalAlign.Center },               right: { anchor: '__container__', align: HorizontalAlign.End }            })            .onClick(() => {               router.pushUrl({url:'pages/search/SearchPage'})            })            .visibility(this.showSearch ? Visibility.Visible : Visibility.None)      }      .backgroundColor('#1296db')      .width('100%')      .height(56)   }}

4、界面效果

 

上一篇:域名不要怎么退还?

下一篇:怎么杀服务器进程?