当前位置: 首页 > news >正文

网站名字备案流程线上引流的八种推广方式

网站名字备案流程,线上引流的八种推广方式,无法访问iis网站,上海企业专属网页本文是系列文章,其他文章见:敲鸿蒙木鱼,积____功德🐶🐶🐶——鸿蒙元服务开发:从入门到放弃(1)敲鸿蒙木鱼,积____功德🐶🐶🐶——鸿蒙元服务开发&am…

本文是系列文章,其他文章见:
敲鸿蒙木鱼,积____功德🐶🐶🐶——鸿蒙元服务开发:从入门到放弃(1)
敲鸿蒙木鱼,积____功德🐶🐶🐶——鸿蒙元服务开发:从入门到放弃(2)

本文完整源码查看funny-widget

简介

因为工作需要,准备开发元服务,所以就想着搞一个电子木鱼的DEMO学习一下元服务以及桌面卡片的功能开发知识。

详细了解HarmonyOS的元服务,可查看官方介绍

涉及知识点

  • 元服务开发流程
  • 加载图片
  • 播放音频
  • 开发调试
  • 组件代码在卡片和元服务间共享
  • 数据在卡片和元服务间共享

应用内卡片开发

因为元服务卡片存在音频播放问题,在咨询了官方技术支持后,确定是无法播放的。

在官方文档中看到了使用call事件拉起指定UIAbility到后台

因此使用了此方法进行音频播放功能验证。

卡片代码
@Entry
@Component
struct WidgetEventCallCard {@LocalStorageProp('formId') formId: string = '12400633174999288';build() {Column() {Row() {Column() {Button() {Text('playLocalSound').padding(16)}.onClick(() => {console.info('click playLocalSound')postCardAction(this, {action: 'call',abilityName: 'WidgetEventCallEntryAbility', // 只能跳转到当前应用下的UIAbilityparams: {formId: '12400633174999288',method: 'playLocalSound' // 在EntryAbility中调用的方法名}});console.info('after click playLocalSound')})Button() {Text('playOnlineSound').padding(16)}.onClick(() => {console.info('click playOnlineSound')postCardAction(this, {action: 'call',abilityName: 'WidgetEventCallEntryAbility', // 只能跳转到当前应用下的UIAbilityparams: {formId: '12400633174999288',method: 'playOnlineSound' // 在EntryAbility中调用的方法名}});console.info('after click playOnlineSound')})}}.width('100%').height('80%').justifyContent(FlexAlign.Center)}.width('100%').height('100%').alignItems(HorizontalAlign.Center)}
}

卡片上添加了两个按钮分别用来测试本地音频播放和在线音频播放。

Entry代码
import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
import { promptAction, window } from '@kit.ArkUI';
import { BusinessError } from '@kit.BasicServicesKit';
import { rpc } from '@kit.IPCKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { media } from '@kit.MediaKit';
import { AudioManager } from '../utils/AudioManager';const TAG: string = 'WidgetEventCallEntryAbility';
const DOMAIN_NUMBER: number = 0xFF00;
const CONST_NUMBER_1: number = 1;
const CONST_NUMBER_2: number = 2;class MyParcelable implements rpc.Parcelable {num: number;str: string;constructor(num: number, str: string) {this.num = num;this.str = str;}marshalling(messageSequence: rpc.MessageSequence): boolean {messageSequence.writeInt(this.num);messageSequence.writeString(this.str);return true;}unmarshalling(messageSequence: rpc.MessageSequence): boolean {this.num = messageSequence.readInt();this.str = messageSequence.readString();return true;}
}export default class WidgetEventCallEntryAbility extends UIAbility {// 如果UIAbility第一次启动,在收到call事件后会触发onCreate生命周期回调onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {try {// 监听call事件所需的方法this.callee.on('playLocalSound', (data: rpc.MessageSequence) => {// 获取call事件中传递的所有参数hilog.info(DOMAIN_NUMBER, TAG, `playLocalSound param:  ${JSON.stringify(data.readString())}`);AudioManager.shared.playSound()return new MyParcelable(CONST_NUMBER_1, 'aaa');});this.callee.on('playOnlineSound', (data: rpc.MessageSequence) => {// 获取call事件中传递的所有参数hilog.info(DOMAIN_NUMBER, TAG, `playOnlineSound param:  ${JSON.stringify(data.readString())}`);AudioManager.shared.playOnlineSound()return new MyParcelable(CONST_NUMBER_1, 'aaa');});} catch (err) {hilog.error(DOMAIN_NUMBER, TAG, `Failed to register callee on. Cause: ${JSON.stringify(err as BusinessError)}`);}}// 进程退出时,解除监听onDestroy(): void | Promise<void> {try {this.callee.off('playLocalSound');this.callee.off('playOnlineSound');} catch (err) {hilog.error(DOMAIN_NUMBER, TAG, `Failed to register callee off. Cause: ${JSON.stringify(err as BusinessError)}`);}}onWindowStageCreate(windowStage: window.WindowStage): void {// Main window is created, set main page for this abilityhilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');windowStage.loadContent('pages/Index', (err) => {if (err.code) {hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');return;}hilog.info(0x0000, 'testTag', 'Succeeded in loading the content.');});}onWindowStageDestroy(): void {// Main window is destroyed, release UI related resourceshilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy');}onForeground(): void {// Ability has brought to foregroundhilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground');}onBackground(): void {// Ability has back to backgroundhilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground');}
}

主要就是在onCreate方法中监听playLocalSoundplayOnlineSound两个call事件。

AudioManager
import { media } from '@kit.MediaKit'
import { BusinessError } from '@kit.BasicServicesKit'
import { hilog } from '@kit.PerformanceAnalysisKit'
import { common } from '@kit.AbilityKit'export class AudioManager {static shared = new AudioManager()playSound() {this.log(`AudioManager playSound`)this.playLocalSound()}log(message: string) {hilog.info(0x0000, '音频', '%{public}s', `${message}`);console.info(`[音频]${message}`);}isSeek: boolean = falsecount: number = 0setAVPlayerCallback(avPlayer: media.AVPlayer) {this.log('setAVPlayerCallback')// seek操作结果回调函数avPlayer.on('seekDone', (seekDoneTime: number) => {this.log(`AVPlayer seek succeeded, seek time is ${seekDoneTime}`)})// error回调监听函数,当avPlayer在操作过程中出现错误时调用 reset接口触发重置流程avPlayer.on('error', (err: BusinessError) => {this.log(`avPlayer on error, code is ${err.code}, message is ${err.message}`)avPlayer.reset(); // 调用reset重置资源,触发idle状态})// 状态机变化回调函数avPlayer.on('stateChange', async (state: media.AVPlayerState, reason: media.StateChangeReason) => {this.log(`stateChange回调:${state}${reason.toString()}`)switch (state) {case 'idle': // 成功调用reset接口后触发该状态机上报console.info('AVPlayer state idle called.');avPlayer.release(); // 调用release接口销毁实例对象break;case 'initialized': // avplayer 设置播放源后触发该状态上报console.info('AVPlayer state initialized called.');avPlayer.prepare();break;case 'prepared': // prepare调用成功后上报该状态机console.info('AVPlayer state prepared called.');avPlayer.play(); // 调用播放接口开始播放break;case 'playing': // play成功调用后触发该状态机上报console.info('AVPlayer state playing called.');if (this.count !== 0) {if (this.isSeek) {console.info('AVPlayer start to seek.');avPlayer.seek(avPlayer.duration); //seek到音频末尾} else {// 当播放模式不支持seek操作时继续播放到结尾console.info('AVPlayer wait to play end.');}} else {avPlayer.pause(); // 调用暂停接口暂停播放}this.count++;break;case 'paused': // pause成功调用后触发该状态机上报console.info('AVPlayer state paused called.');avPlayer.play(); // 再次播放接口开始播放break;case 'completed': // 播放结束后触发该状态机上报console.info('AVPlayer state completed called.');avPlayer.stop(); //调用播放结束接口break;case 'stopped': // stop接口成功调用后触发该状态机上报console.info('AVPlayer state stopped called.');avPlayer.reset(); // 调用reset接口初始化avplayer状态break;case 'released':console.info('AVPlayer state released called.');break;case 'error':console.info('AVPlayer state error called.');break;default:console.info('AVPlayer state unknown called.');break;}})}async playLocalSound() {hilog.info(0x0000, '音频', '%{public}s', 'playLocalSound');console.debug(`[音频]playLocalSound`)try {// 创建avPlayer实例对象let avPlayer: media.AVPlayer = await media.createAVPlayer();this.log(`createAVPlayer success`)// 创建状态机变化回调函数this.setAVPlayerCallback(avPlayer);// 通过UIAbilityContext的resourceManager成员的getRawFd接口获取媒体资源播放地址// 返回类型为{fd,offset,length},fd为HAP包fd地址,offset为媒体资源偏移量,length为播放长度let context = getContext(this) as common.ExtensionContext;this.log(`getContext:context=${context}`)// hilog.info(0x0000, '组件', '%{public}s', `playLocalSound:context扩展名=${context.extensionAbilityInfo.name}}`);let fileDescriptor = await context.resourceManager.getRawFd('dang.mp3');this.log(`playLocalSound:fileDescriptor.length=${fileDescriptor.length}}`)let avFileDescriptor: media.AVFileDescriptor ={ fd: fileDescriptor.fd, offset: fileDescriptor.offset, length: fileDescriptor.length };this.isSeek = true; // 支持seek操作// 为fdSrc赋值触发initialized状态机上报avPlayer.fdSrc = avFileDescriptor;} catch (e) {this.log(`playLocalSound出错:${e.toString()}`)}}// 以下demo为通过url设置网络地址来实现播放直播码流的demoasync playOnlineSound() {this.log(`playOnlineSound`)// 创建avPlayer实例对象let avPlayer: media.AVPlayer = await media.createAVPlayer();this.log(`createAVPlayer success`)// 创建状态机变化回调函数this.setAVPlayerCallback(avPlayer);avPlayer.url = 'https://clemmensen.top/static/muyu.mp3';}
}

音频播放代码提供了本地和在线两个播放逻辑。

结论

期望:
在应用未运行的情况下,用卡片call方法拉起App到后台并播放音频。

实测:
播放rawfile音频失败
播放在线音频成功

向官方技术支持咨询:

鸿蒙技术支持
开发者你好,这边测试本地是有音频的敲击声啊159******50
要先杀掉应用再点;正常场景是“应用未运行的情况下”点击卡片播放音频鸿蒙技术支持
确实是的,正在内部分析中鸿蒙技术支持
开发者你好,初步结论是 let context = getContext(this) as common.ExtensionContext;
此场景中上述context获取不到,导致不能读取rawfile文件159******50
这个我清楚,日志就能看到的。问题是怎么解决呢?有没有其他方案读取rawfile?鸿蒙技术支持
当前卡片框架不支持获取context,这个确认为当前规格159******50let context = getContext(this) as common.ExtensionContext;”这个已经是通过call事件拉起application,走到application的代码里了,不算卡片代码的运行环境吧?鸿蒙技术支持
开发者你好,通过call事件去拉起还是借助卡片的能力,卡片里面本身就是受限功能
总结与体会

😅😅😅在鸿蒙系统初期开发这类小众功能真的是遍地是坑。
普通的应用界面因为有大量应用在开发,所以坑填的相对快(但也不少),像元服务、卡片、音频,这样的混合领域,坑得数量可能超出你预期,开发者在前期做开发计划时尽量保守一些,不要脑袋一热,用iOS/Android的开发经验来轻率定时间进度。


文章转载自:
http://dinncodistant.tpps.cn
http://dinncooverlusty.tpps.cn
http://dinncoendosternite.tpps.cn
http://dinncogreenbug.tpps.cn
http://dinncofossate.tpps.cn
http://dinncoinundant.tpps.cn
http://dinncocytospectrophotometry.tpps.cn
http://dinncoyoicks.tpps.cn
http://dinncoisotope.tpps.cn
http://dinncotashkend.tpps.cn
http://dinncoperigean.tpps.cn
http://dinncoclearweed.tpps.cn
http://dinncojoning.tpps.cn
http://dinncoappendix.tpps.cn
http://dinncodoubler.tpps.cn
http://dinnconoonflower.tpps.cn
http://dinncotubbiness.tpps.cn
http://dinncodownstate.tpps.cn
http://dinncobandsman.tpps.cn
http://dinncodudley.tpps.cn
http://dinncopreoperative.tpps.cn
http://dinnconegroni.tpps.cn
http://dinncoinlook.tpps.cn
http://dinncobrachycephal.tpps.cn
http://dinncohuffy.tpps.cn
http://dinncomotorcar.tpps.cn
http://dinncoparentheses.tpps.cn
http://dinncoromanza.tpps.cn
http://dinncoburweed.tpps.cn
http://dinncoscatterbrain.tpps.cn
http://dinncomulch.tpps.cn
http://dinncophobos.tpps.cn
http://dinncogarut.tpps.cn
http://dinncocreationary.tpps.cn
http://dinncoexposition.tpps.cn
http://dinncotisane.tpps.cn
http://dinncokame.tpps.cn
http://dinncodissolvingly.tpps.cn
http://dinncodebone.tpps.cn
http://dinncoundershirt.tpps.cn
http://dinncoabasable.tpps.cn
http://dinncounincumbered.tpps.cn
http://dinncounguardedly.tpps.cn
http://dinncolabia.tpps.cn
http://dinncopeopleware.tpps.cn
http://dinncocalamanco.tpps.cn
http://dinncobloodguilty.tpps.cn
http://dinncomnas.tpps.cn
http://dinncodrag.tpps.cn
http://dinncomiddy.tpps.cn
http://dinncoeartab.tpps.cn
http://dinncodisroot.tpps.cn
http://dinncoinfatuated.tpps.cn
http://dinncoregulation.tpps.cn
http://dinncowaistcoat.tpps.cn
http://dinncodebarkation.tpps.cn
http://dinncofacial.tpps.cn
http://dinncocommerce.tpps.cn
http://dinncobechamel.tpps.cn
http://dinncotime.tpps.cn
http://dinncospillway.tpps.cn
http://dinncocheering.tpps.cn
http://dinncoototoxic.tpps.cn
http://dinncokimbundu.tpps.cn
http://dinncocnaa.tpps.cn
http://dinncoisogony.tpps.cn
http://dinncoprelapsarian.tpps.cn
http://dinncorechoose.tpps.cn
http://dinncodensimeter.tpps.cn
http://dinncoiterate.tpps.cn
http://dinncopeat.tpps.cn
http://dinncoradiologist.tpps.cn
http://dinnconival.tpps.cn
http://dinncolistless.tpps.cn
http://dinncotriploblastic.tpps.cn
http://dinnconaturism.tpps.cn
http://dinncosupracrustal.tpps.cn
http://dinncoeozoic.tpps.cn
http://dinncochordata.tpps.cn
http://dinncoantiimperialism.tpps.cn
http://dinncolatheman.tpps.cn
http://dinncoremarkable.tpps.cn
http://dinncomismate.tpps.cn
http://dinncocommendatory.tpps.cn
http://dinncoapod.tpps.cn
http://dinncosupervisee.tpps.cn
http://dinncoeidoptometry.tpps.cn
http://dinncofernery.tpps.cn
http://dinncoseditty.tpps.cn
http://dinncothrone.tpps.cn
http://dinncomesocephalon.tpps.cn
http://dinncojudea.tpps.cn
http://dinncozamarra.tpps.cn
http://dinncononhero.tpps.cn
http://dinncolipin.tpps.cn
http://dinncomarginal.tpps.cn
http://dinncodefecator.tpps.cn
http://dinncoinfiltrative.tpps.cn
http://dinncostimulant.tpps.cn
http://dinncoassessable.tpps.cn
http://www.dinnco.com/news/143341.html

相关文章:

  • 营销型网站建设的目标是技术培训
  • 网站预约挂号怎么做网站seo优化8888
  • 网站建设迅雷公司网址怎么注册
  • 龙岗汤坑社区网站建设seo网站推广软件
  • 王也微信头像优化关键词怎么做
  • 带后台管理的网站模板品牌seo培训咨询
  • 华为网站的建设目标网站开发
  • 杭州网站设计建立企业网站谷歌seo价格
  • 网站登陆界面怎么做上海网站建设优化
  • 怎样建一个个人网站湖北网络推广
  • 动漫网站开发传统营销与网络营销的整合方法
  • 衡水网站建设百度链接提交工具
  • 深圳大型商城网站建设优化培训方式
  • 上海临平路网站建设人力资源培训机构
  • .design 域名的网站网站关键词优化软件
  • 网站建设内部因素汕头seo关键词排名
  • tp5手机网站开发怎么办网站平台
  • 昆明网站建设技术公司免费建站免费网站
  • 手机网站后台企业营销平台
  • 2022国际国内重大新闻推广优化网站排名
  • 软装设计师培训中心南昌seo营销
  • 中央新闻联播直播 今天四川seo选哪家
  • 网站备案 英文深圳竞价托管公司
  • 自己建的网站如何做海外推广对网络营销的认识800字
  • 在哪里做网站比较好semantics
  • 哪个网站可以做任务赚钱的阿里指数官网最新版本
  • 学校做网站的软件新网站推广方法
  • 电子商务网站开发背景怎么让某个关键词排名上去
  • 移动端h5是什么影响seo排名的因素
  • cms建立网站谷歌广告推广